Comment spécifier le type de retour «nullable» avec des indices de type

177

Supposons que j'ai une fonction:

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

Comment spécifier le type de retour pour quelque chose qui peut l'être None?

exfizik
la source

Réponses:

279

Vous cherchez Optional.

Étant donné que votre type de retour peut être datetime(comme renvoyé de datetime.utcnow()) ou Nonevous devez utiliser Optional[datetime]:

from typing import Optional

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

De la documentation sur la saisie, Optionalest un raccourci pour:

Optional[X]équivaut à Union[X, None].

Union[X, Y]signifie une valeur de type Xou Y.


Si vous voulez être explicite en raison de préoccupations sur lesquelles d'autres pourraient trébucher Optionalet ne pas se rendre compte de sa signification, vous pouvez toujours utiliser Union:

from typing import Union

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

Mais je doute que ce soit une bonne idée, Optionalc'est un nom indicatif et cela permet d'économiser quelques frappes.

Comme indiqué dans les commentaires de @ Michael0x2a Union[T, None]est transformé en Union[T, type(None)]donc pas besoin d'utiliser typeici.

Visuellement, ceux-ci peuvent différer mais par programme, dans les deux cas, le résultat est exactement le même ; Union[datetime.datetime, NoneType]sera le type stocké dans 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]}

* Utilisez typing.get_type_hintspour saisir l' __annotations__attribut des objets au lieu d'y accéder directement.

Dimitris Fasarakis Hilliard
la source
10
Vous pouvez simplifier Union[datetime, type(None)]à Union[datetime, None]- selon PEP 484 , en utilisant Nonedans une annotation de type est toujours considéré comme équivalent à type(None). (La typingdocumentation utilise Noneen fait dans la plupart des cas, mais pas ici, ce qui est un oubli).
Michael0x2a
@ Michael0x2a ne le savait pas, intéressant. Ajouté il :)
Dimitris Fasarakis Hilliard
4
Je suis allé de l'avant et j'ai soumis un correctif pour résoudre ce problème tout à l'heure, donc j'espère que la documentation sera plus cohérente à ce sujet dans un proche avenir!
Michael0x2a du
1
Le Optional[T]type est bien connu dans la communauté de programmation fonctionnelle. Le lecteur ne saura pas seulement que cela signifie Union[T, None], mais reconnaîtra également le modèle d'utilisation que la fonction doit renvoyer None lorsqu'il n'y a pas de réponse significative, qu'il y a une erreur ou que le résultat n'est pas trouvé.
sem.22