Python Language
Type conseils
Recherche…
Syntaxe
- typing.Callable [[int, str], None] -> def func (a: int, b: str) -> Aucun
- typing.Mapping [str, int] -> {"a": 1, "b": 2, "c": 3}
- typing.List [int] -> [1, 2, 3]
- typing.Set [int] -> {1, 2, 3}
- typing.Optional [int] -> Aucun ou int
- typing.Sequence [int] -> [1, 2, 3] ou (1, 2, 3)
- taper.Any -> N'importe quel type
- taper.Union [int, str] -> 1 ou "1"
- T = typing.TypeVar ('T') -> Type générique
Remarques
L'indication de type, spécifiée dans PEP 484
, est une solution formalisée permettant d'indiquer statiquement le type d'une valeur pour le code Python. En apparaissant à côté du module de typing
, les typing
type offrent aux utilisateurs Python la possibilité d’annoter leur code, aidant ainsi les vérificateurs de type tout en documentant indirectement leur code avec plus d’informations.
Types génériques
Le typing.TypeVar
est une fabrique de type générique. Son objectif principal est de servir de paramètre / espace réservé pour les annotations génériques de fonction / classe / méthode:
import typing
T = typing.TypeVar("T")
def get_first_element(l: typing.Sequence[T]) -> T:
"""Gets the first element of a sequence."""
return l[0]
Ajouter des types à une fonction
Prenons un exemple de fonction qui reçoit deux arguments et renvoie une valeur indiquant leur somme:
def two_sum(a, b):
return a + b
En regardant ce code, on ne peut pas et sans doute indiquer le type des arguments pour la fonction two_sum
. Il fonctionne à la fois avec les valeurs int
:
print(two_sum(2, 1)) # result: 3
et avec des cordes:
print(two_sum("a", "b")) # result: "ab"
et avec d'autres valeurs, telles que les list
s, tuple
s et cetera.
En raison de la nature dynamique des types python, où beaucoup sont applicables à une opération donnée, tout vérificateur de type ne pourrait pas raisonnablement affirmer si un appel pour cette fonction devrait être autorisé ou non.
Pour aider notre vérificateur de types, nous pouvons maintenant lui fournir des indications de type dans la définition de fonction, indiquant le type que nous autorisons.
Pour indiquer que nous voulons seulement autoriser les types int
nous pouvons changer notre définition de fonction pour qu'elle ressemble à:
def two_sum(a: int, b: int):
return a + b
Les annotations suivent le nom de l' argument et sont séparés par un :
caractère.
De même, pour indiquer que seuls les types str
sont autorisés, nous modifierons notre fonction pour la spécifier:
def two_sum(a: str, b: str):
return a + b
En plus de spécifier le type des arguments, on pourrait également indiquer la valeur de retour d'un appel de fonction. Cela se fait en ajoutant le caractère ->
suivi du type après la parenthèse fermante dans la liste des arguments, mais avant le :
à la fin de la déclaration de la fonction:
def two_sum(a: int, b: int) -> int:
return a + b
Maintenant, nous avons indiqué que la valeur de retour lors de l'appel à two_sum
devrait être de type int
. De même, nous pouvons définir des valeurs appropriées pour str
, float
, list
, set
et autres.
Bien que les indicateurs de type soient principalement utilisés par les vérificateurs de type et les IDE, il est parfois nécessaire de les récupérer. Cela peut être fait en utilisant l' __annotations__
spécial __annotations__
:
two_sum.__annotations__
# {'a': <class 'int'>, 'b': <class 'int'>, 'return': <class 'int'>}
Membres de la classe et méthodes
class A:
x = None # type: float
def __init__(self, x: float) -> None:
"""
self should not be annotated
init should be annotated to return None
"""
self.x = x
@classmethod
def from_int(cls, x: int) -> 'A':
"""
cls should not be annotated
Use forward reference to refer to current class with string literal 'A'
"""
return cls(float(x))
La référence en aval de la classe en cours est nécessaire car les annotations sont évaluées lorsque la fonction est définie. Les références directes peuvent également être utilisées lorsque vous faites référence à une classe qui provoquerait une importation circulaire si elle était importée.
Variables et attributs
Les variables sont annotées en utilisant les commentaires:
x = 3 # type: int
x = negate(x)
x = 'a type-checker might catch this error'
À partir de Python 3.6, il existe également une nouvelle syntaxe pour les annotations de variables . Le code ci-dessus pourrait utiliser le formulaire
x: int = 3
Contrairement aux commentaires, il est également possible d’ajouter un indice de type à une variable qui n’a pas été déclarée précédemment, sans lui donner de valeur:
y: int
En outre, si elles sont utilisées au niveau du module ou de la classe, les indications de type peuvent être récupérées à l'aide de typing.get_type_hints(class_or_module)
:
class Foo:
x: int
y: str = 'abc'
print(typing.get_type_hints(Foo))
# ChainMap({'x': <class 'int'>, 'y': <class 'str'>}, {})
Vous pouvez également y accéder en utilisant la variable ou l'attribut spécial __annotations__
:
x: int
print(__annotations__)
# {'x': <class 'int'>}
class C:
s: str
print(C.__annotations__)
# {'s': <class 'str'>}
NomméTuple
La création d'un élément nommé avec des indications de type se fait à l'aide de la fonction NamedTuple du module de typing
:
import typing
Point = typing.NamedTuple('Point', [('x', int), ('y', int)])
Notez que le nom du type résultant est le premier argument de la fonction, mais qu'il doit être affecté à une variable du même nom pour faciliter le travail des vérificateurs de type.
Indiquer des astuces pour les arguments de mots clés
def hello_world(greeting: str = 'Hello'):
print(greeting + ' world!')
Notez les espaces autour du signe égal, par opposition à la façon dont les arguments sont généralement stylés.