Optional[...]
est une notation abrégée pour Union[..., None]
en indiquant au vérificateur de type qu'un objet du type spécifique est requis, o None
est nécessaire. ...
signifie tout indice de type valide y compris les types de composés complexes ou un Union[]
de plus de types. Chaque fois que vous avez un argument de mot-clé avec une valeur par défaut None
vous devez utiliser Optional
. (Remarque : si vous utilisez Python 3.10 ou une version plus récente, PEP 604 a introduit une meilleure syntaxe, voir ci-dessous).
Donc pour vos deux exemples, vous avez dict
y list
mais la valeur par défaut de l'option a
L'argument du mot-clé montre que None
est également autorisé, alors utilisez Optional[...]
:
from typing import Optional
def test(a: Optional[dict] = None) -> None:
#print(a) ==> {'a': 1234}
#or
#print(a) ==> None
def test(a: Optional[list] = None) -> None:
#print(a) ==> [1, 2, 3, 4, 'a', 'b']
#or
#print(a) ==> None
Il n'y a techniquement aucune différence entre l'utilisation de Optional[]
sur un Union[]
ou simplement en ajoutant None
à la Union[]
. Donc Optional[Union[str, int]]
y Union[str, int, None]
sont exactement la même chose.
Personnellement, je m'en tiendrais à toujours en utilisant Optional[]
lors de la définition du type d'un argument de mot-clé qui utilise la fonction = None
pour définir une valeur par défaut, ceci documente la raison pour laquelle None
est mieux autorisée. En outre, il est plus facile de déplacer le Union[...]
dans un alias de type distinct, ou pour supprimer ultérieurement l'élément Optional[...]
partie si un argument devient obligatoire.
Par exemple, disons que vous avez
from typing import Optional, Union
def api_function(optional_argument: Optional[Union[str, int]] = None) -> None:
"""Frob the fooznar.
If optional_argument is given, it must be an id of the fooznar subwidget
to filter on. The id should be a string, or for backwards compatibility,
an integer is also accepted.
"""
alors la documentation est améliorée en retirant le Union[str, int]
en un alias de type :
from typing import Optional, Union
# subwidget ids used to be integers, now they are strings. Support both.
SubWidgetId = Union[str, int]
def api_function(optional_argument: Optional[SubWidgetId] = None) -> None:
"""Frob the fooznar.
If optional_argument is given, it must be an id of the fooznar subwidget
to filter on. The id should be a string, or for backwards compatibility,
an integer is also accepted.
"""
Le remaniement visant à déplacer le Union[]
en un alias a été rendu d'autant plus facile que Optional[...]
a été utilisé à la place de Union[str, int, None]
. Le site None
n'est pas un "id de subwidget" après tout, il ne fait pas partie de la valeur, None
est destiné à signaler l'absence d'une valeur.
Remarque : à moins que votre code ne doive supporter Python 3.9 ou une version plus récente, il est préférable d'éviter d'utiliser les types conteneurs de la bibliothèque standard dans les indications de type, car vous ne pouvez rien dire sur les types qu'ils doivent contenir. Ainsi, au lieu de dict
y list
utiliser typing.Dict
y typing.List
respectivement. Et lorsque seulement lecture d'un type de conteneur, vous pouvez tout aussi bien accepter n'importe quel type de conteneur abstrait immuable ; les listes et les tuples sont des Sequence
tandis que dict
es un Mapping
type :
from typing import Mapping, Optional, Sequence, Union
def test(a: Optional[Mapping[str, int]] = None) -> None:
"""accepts an optional map with string keys and integer values"""
# print(a) ==> {'a': 1234}
# or
# print(a) ==> None
def test(a: Optional[Sequence[Union[int, str]]] = None) -> None:
"""accepts an optional sequence of integers and strings
# print(a) ==> [1, 2, 3, 4, 'a', 'b']
# or
# print(a) ==> None
À partir de la version 3.9 de Python, les types de conteneurs standard ont tous été mis à jour afin de pouvoir les utiliser dans les indications de type. PEP 585 . Mais alors que vous, maintenant peut utilice dict[str, int]
o list[Union[int, str]]
mais vous pouvez tout de même utiliser la méthode plus expressive Mapping
y Sequence
pour indiquer qu'une fonction ne modifiera pas le contenu (il sera traité comme étant en lecture seule) et que les fonctions fonctionneront avec des fichiers de type tout qui fonctionne comme un mappage ou une séquence, respectivement.
Python 3.10 introduit la fonction |
l'opérateur d'union dans les indications de type, voir PEP 604 . Au lieu de Union[str, int]
vous pouvez écrire str | int
. En accord avec les autres langages à indication de type, la manière préférée (et plus concise) de désigner un argument optionnel dans Python 3.10 et plus est désormais la suivante Type | None
par exemple str | None
o list | None
.
1 votes
Quel est l'avantage d'utiliser Optional ou Union[..., None] plutôt que : list = None ? Cette syntaxe n'est-elle pas déjà explicite ?
2 votes
@gohu - Vous avez raison. Pour les arguments de mots-clés, les deux
mypy
et les IDE sont capables de supposer l'évidence et de les traiter automatiquement comme desOptional
. Voir ma réponse ci-dessous.