336 votes

Comment spécifier un type de retour "nullable" avec des indices de type ?

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 puis-je spécifier le type de retour pour quelque chose qui peut être None ?

3 votes

Mauvaise dénomination appliquée dans typing paquet. Il peut s'agir Nullable[X] comme un équivalent pour Union[None, X] . Il n'est donc pas nécessaire d'expliquer que Optional n'est pas pour l'argument facultatif docs.python.org/3/library/typing.html#typing.Optional

525voto

Jim Points 8793

Vous êtes à la recherche de Optional .

Puisque votre type de retour peut être soit datetime (tel que renvoyé par datetime.utcnow() ) ou None vous devez utiliser Optional[datetime] :

from typing import Optional

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

Extrait de la documentation sur la saisie, Optional est une abréviation de :

Optional[X] est équivalent à Union[X, None] .

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


Si vous voulez être explicite parce que vous craignez que d'autres personnes ne tombent sur Optional et ne pas réaliser 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, Optional est un nom indicatif et il permet d'économiser quelques frappes de clavier.

Comme indiqué dans les commentaires par @Michael0x2a <code>Union[T, None]</code> est transformé en <code>Union[T, type(None)]</code> il n'est donc pas nécessaire d'utiliser <code>type</code> ici.

Visuellement, ils peuvent être différents, mais en termes de programmation, dans les deux cas, le résultat est le suivant exactement la même chose ; 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_hints pour saisir les objets __annotations__ au lieu d'y accéder directement.

16 votes

Vous pouvez simplifier Union[datetime, type(None)] à Union[datetime, None] -- selon PEP 484 en utilisant None dans une annotation de type est toujours traitée comme étant équivalente à type(None) . (Le typing La documentation utilise en fait None dans la plupart des cas, mais ne le fait pas ici, ce qui est un oubli).

0 votes

@Michael0x2a ne le savait pas, intéressant. Je l'ai ajouté :)

5 votes

Je me suis lancé et j'ai soumis un patch pour corriger ce problème à l'instant, donc j'espère que la documentation sera plus cohérente à ce sujet dans un futur proche !

11voto

elano7 Points 397

Vous pourriez simplement utiliser la ligne verticale datetime | None (similaire à l'opérateur OR) :

def get_some_date(some_argument: int=None) -> datetime | None:
   # rest of code

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X