Como especificar o tipo de retorno "anulável" com dicas de tipo

177

Suponha que eu tenha uma função:

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

Como especifico o tipo de retorno para algo que pode ser None?

exfizik
fonte

Respostas:

279

Você está procurando Optional.

Como seu tipo de retorno pode ser datetime(como retornado datetime.utcnow()) ou Nonevocê deve usar Optional[datetime]:

from typing import Optional

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

A partir da documentação sobre digitação, Optionalé uma abreviação de:

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

onde Union[X, Y]significa um valor do tipo Xou Y.


Se você quiser ser explícito devido a preocupações de que outras pessoas possam tropeçar Optionale não perceber o significado, sempre use Union:

from typing import Union

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

Mas duvido que seja uma boa ideia, Optionalseja um nome indicativo e economize algumas teclas.

Como apontado nos comentários de @ Michael0x2a, Union[T, None]é transformado para Union[T, type(None)]que não seja necessário usar typeaqui.

Visualmente, eles podem diferir, mas programaticamente, em ambos os casos, o resultado é exatamente o mesmo ; Union[datetime.datetime, NoneType]será o tipo armazenado em 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 pegar o __annotations__atributo dos objetos em vez de acessá-lo diretamente.

Dimitris Fasarakis Hilliard
fonte
10
Você pode simplificar Union[datetime, type(None)]para Union[datetime, None]- de acordo com o PEP 484 , usar Noneem uma anotação de tipo sempre é tratado como equivalente type(None). (A typingdocumentação realmente usa Nonena maioria dos casos, mas não aqui, o que é uma supervisão).
Michael0x2a
@ Michael0x2a não sabia disso, interessante. Adicionado :)
Dimitris Fasarakis Hilliard 11/11/16
4
Fui em frente e enviei um patch para corrigir isso agora, por isso espero que os documentos sejam mais consistentes sobre isso em um futuro próximo!
Michael0x2a
1
O Optional[T]tipo é bem conhecido na comunidade de programação funcional. O leitor não apenas saberá o que significa Union[T, None], mas também reconhecerá o padrão de uso que a função retornará None quando não houver resposta significativa, houver um erro ou o resultado não for encontrado.
wks