Historique de la question
Les annotations de fonction sont apparues dans Python 3.0, et le mécanisme des type hints est décrit dans le PEP 484, ajouté avec la version 3.5. Cet outil a été créé pour l'analyse statique du code, l'auto-complétion et l'amélioration de la lisibilité - la bibliothèque standard de types (typing) permet d'indiquer explicitement les types attendus des variables, des arguments et des valeurs de retour des fonctions.
Problème
Python est un langage dynamique où les types de variables peuvent changer pendant l'exécution, ce qui peut entraîner des erreurs uniquement au moment de l'exécution du programme. Les annotations n'affectent pas l'exécution du code, mais une mauvaise utilisation peut donner aux programmeurs un faux sentiment de "typage strict".
Solution
Les annotations de type sont utilisées pour la documentation, la vérification automatique avec des outils comme mypy, pylance, pyright et similaires, ainsi que pour l'intégration avec les IDE. Elles sont mises en œuvre par des deux-points après le nom de l'argument et une flèche après la liste des paramètres :**
def greet(name: str, times: int = 1) -> None: for _ in range(times): print(f"Hello, {name}!") # Annotation correcte pour une fonction de traitement de dictionnaire from typing import Dict, List def transform(data: Dict[str, List[int]]) -> float: return sum(sum(lst) for lst in data.values()) / 10
Caractéristiques clés :
Python peut-il "automatiquement" vérifier la conformité aux types déclarés dans les annotations ?
Non ! La vérification des types se fait uniquement par des outils externes d'analyse statique, comme mypy. À l'exécution, Python ignore complètement le contenu des annotations.
def f(x: int): return x * 2 print(f('oops')) # Type str, aucune erreur ne sera levée !
Où sont stockées les annotations et comment les obtenir à l'exécution, pourquoi cela pourrait-il être nécessaire ?
Elles sont stockées dans un attribut spécial annotations :
def add(x: int, y: int) -> int: return x + y print(add.__annotations__) # {'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}
Cela est utilisé par des bibliothèques tierces pour la validation des données, l'auto-génération de documentation, la sérialisation, etc.
Peut-on annoter n'importe quelle variable, uniquement des fonctions, que se passe-t-il dans l'espace global ?
On peut annoter à la fois des variables locales et globales via les deux-points, cela n'affecte pas non plus l'exécution :
index: int = 0 def func(x: 'User') -> None: ...
Dans un projet d'entreprise, tous les développeurs ont commencé à intégrer activement des annotations, mais les types réels des arguments des fonctions ne correspondaient souvent pas à ceux indiqués. Python laissait passer ces erreurs, et des bogues inattendus apparaissaient uniquement au cœur de la logique métier. La configuration de mypy était absente.
Avantages :
Inconvénients :
Utilisation des type hints et lancement obligatoire de mypy dans le CI, ainsi que l'auto-génération de documentation à partir des annotations :
Avantages :
Inconvénients :