Cómo especificar el tipo de retorno "anulable" con sugerencias de tipo

177

Supongamos que tengo una función:

def get_some_date(some_argument: int=None) -> %datetime_or_None%:
    if some_argument is not None and some_argument == 1:
        return datetime.utcnow()
    else:
        return None

¿Cómo especifico el tipo de retorno para algo que puede ser None?

exfizik
fuente

Respuestas:

279

Usted está buscando Optional.

Dado que su tipo de devolución puede ser datetime(tal como se devuelve desde datetime.utcnow()) o Nonedebe usar Optional[datetime]:

from typing import Optional

def get_some_date(some_argument: int=None) -> Optional[datetime]:
    # as defined

De la documentación sobre mecanografía, Optionalse abrevia para:

Optional[X]es equivalente a Union[X, None].

donde Union[X, Y]significa un valor de tipo Xo Y.


Si desea ser explícito debido a las preocupaciones con las que otros podrían tropezar Optionaly no darse cuenta de su significado, siempre puede usar Union:

from typing import Union

def get_some_date(some_argument: int=None) -> Union[datetime, None]:

Pero dudo que esta sea una buena idea, Optionales un nombre indicativo y ahorra un par de pulsaciones de teclas.

Como se señaló en los comentarios de @ Michael0x2a, Union[T, None]se transforma para Union[T, type(None)]que no sea necesario usarlo typeaquí.

Visualmente estos pueden diferir pero programáticamente, en ambos casos, el resultado es exactamente el mismo ; Union[datetime.datetime, NoneType]será el tipo almacenado en get_some_date.__annotations__* :

>>> from typing import get_type_hints
>>> print(get_type_hints(get_some_date))
{'return': typing.Union[datetime.datetime, NoneType],
 'some_argument': typing.Union[int, NoneType]}

* Use typing.get_type_hintspara agarrar el __annotations__atributo de los objetos en lugar de acceder a él directamente.

Dimitris Fasarakis Hilliard
fuente
10
Puede simplificar Union[datetime, type(None)]a Union[datetime, None]- de acuerdo con PEP 484 , el uso Nonedentro de una anotación de tipo siempre se trata como equivalente a type(None). (La typingdocumentación realmente se usa Noneen la mayoría de los casos, pero no aquí, lo cual es un descuido).
Michael0x2a
@ Michael0x2a no lo sabía, interesante. Añadido :)
Dimitris Fasarakis Hilliard
44
Seguí adelante y envié un parche para solucionar esto en este momento, ¡así que espero que los documentos sean más consistentes al respecto en el futuro cercano!
Michael0x2a
1
El Optional[T]tipo es bien conocido en la comunidad de programación funcional. El lector no solo sabrá lo que significa Union[T, None], sino que también reconocerá el patrón de uso que la función devolverá Ninguno cuando no haya una respuesta significativa, haya un error o no se encuentre el resultado.
semanas