Menu
Français

Annotations de type Python : annotations pour fonctions, listes, dicts et plus

Ce que sont les annotations de type Python, quand elles aident, et la syntaxe pour annoter variables, signatures de fonctions, conteneurs et valeurs optionnelles.

Des annotations qui décrivent, sans imposer

Une annotation de type est une note que tu attaches à un nom — généralement un paramètre de fonction — qui dit « ça devrait être un int », « ceci renvoie une liste de chaînes », et ainsi de suite. Python ne les vérifie pas à l'exécution. Passer une chaîne là où tu as annoté un int ne lève pas d'erreur. Ton éditeur et des outils externes (mypy, pyright, Pylance de VS Code) lisent les annotations et te préviennent avant que le code ne s'exécute.

Le cas le plus simple possible :

main.py
Output
Click Run to see the output here.

name: str annote le paramètre. -> str annote la valeur de retour. Les deux appels s'exécutent. Le second est faux — un type checker statique le signalerait — mais Python lui-même le traite volontiers parce que 42 se trouve supporter l'interpolation f"{...}".

C'est le modèle mental crucial : les annotations sont de la documentation qu'une machine peut lire. Elles ne changent pas l'exécution.

Pourquoi se donner la peine ?

Trois gains concrets, dans l'ordre de la rapidité avec laquelle ils paient :

  1. Ton éditeur devient plus intelligent. L'auto-complétion montre les bonnes méthodes, les renommages se propagent correctement, et survoler une variable te dit son type.
  2. Les signatures de fonctions deviennent auto-descriptives. def fetch(url: str, timeout: float = 5.0) -> dict: dit à un lecteur exactement quoi passer et ce qu'il va obtenir — pas besoin de lire le corps.
  3. Les type checkers attrapent les erreurs avant que tu exécutes le code. Lancer mypy . sur un projet fait remonter le genre de bugs que les tests unitaires ratent souvent — un None renvoyé là où tu attendais une valeur, un dict utilisé là où une liste va.

Pour un script d'un seul fichier qui n'est que pour toi et seulement pour aujourd'hui, saute les annotations. Pour tout ce sur quoi tu reviendras ou que tu partageras, les quinze secondes qu'elles prennent à écrire paient dans l'heure.

Types intégrés de base

Tu n'as pas besoin d'import pour ceux-ci :

main.py
Output
Click Run to see the output here.

Les annotations de variables (name: str = "Rosa") sont rarement nécessaires — Python déduit le type du côté droit. Garde-les pour les paramètres, les types de retour et le cas occasionnel où le type déduit est ambigu.

Les fonctions qui ne renvoient rien utilisent -> None :

main.py
Output
Click Run to see the output here.

Listes, dicts, tuples et sets

Les conteneurs ont besoin d'une seconde information — ce qu'ils contiennent. Python moderne te laisse indexer les types intégrés directement :

main.py
Output
Click Run to see the output here.

En les lisant à voix haute :

  • list[float] — une liste de floats.
  • dict[str, int] — un dict avec clés string et valeurs int.
  • tuple[float, float] — un tuple d'exactement deux floats.
  • set[str] — un set de strings.

La syntaxe d'indexation list[...], dict[...] fonctionne en Python 3.9 et suivants. Dans du code plus ancien, tu verras List, Dict, Tuple importés depuis typing — même sens, orthographe plus ancienne.

Valeurs optionnelles

« Pourrait être None » est courant. Ça a deux orthographes équivalentes — les deux vont bien, mais la plus récente se lit mieux :

main.py
Output
Click Run to see the output here.

str | None veut dire « une chaîne, ou None ». La syntaxe | fonctionne en Python 3.10+. Dans du code plus ancien tu verras Optional[str] du module typing, qui veut dire la même chose.

Un appelant qui voit -> str | None sait qu'il faut vérifier None avant d'utiliser le résultat — c'est tout l'intérêt de l'annotation.

Types union : ceci ou cela

Quand une valeur pourrait être de plusieurs types, utilise | :

main.py
Output
Click Run to see the output here.

Tu peux unir plus de deux types. int | str | float veut dire « n'importe lequel de ces trois ».

Annoter des variables dans des fonctions

La plupart du temps, Python peut deviner le type d'une variable locale depuis son initialiseur. Tu as seulement besoin d'une annotation quand :

main.py
Output
Click Run to see the output here.
  • Le conteneur commence vide et le type checker ne peut pas deviner son contenu.
  • La valeur pourrait être de plusieurs types et tu veux t'engager sur un seul.
  • Tu veux documenter l'intention pour un lecteur humain.

typing.Any est l'échappatoire — « je ne veux pas annoter ça précisément ». Utilise-le avec parcimonie. Abuser de Any rend le reste de tes annotations sans valeur.

Annoter des classes

Les attributs de classe et les signatures de méthode s'annotent de la même façon que n'importe quelle autre fonction :

main.py
Output
Click Run to see the output here.

Les dataclasses exigent en fait des annotations de type — le décorateur @dataclass les lit pour générer __init__ et __repr__. C'est le seul endroit où les annotations affectent le comportement à l'exécution.

Tuples et le cas « n'importe quelle longueur »

tuple[...] a deux formes qui embrouillent les débutants :

main.py
Output
Click Run to see the output here.
  • tuple[float, float] — exactement deux floats.
  • tuple[int, ...] — un nombre quelconque d'ints. Le ... (un vrai élément de syntaxe dans le système de types) veut dire « et ainsi de suite ».

Callables et alias de type

Quand une fonction prend ou renvoie une autre fonction, utilise Callable :

main.py
Output
Click Run to see the output here.

Callable[[int], int] veut dire « une fonction qui prend un int et renvoie un int ».

Quand une annotation devient répétitive, nomme-la :

main.py
Output
Click Run to see the output here.

Un alias est juste une affectation Python normale. Partout où tu utiliserais la forme longue, le nom court fonctionne.

Lancer un type checker

L'interpréteur de Python ignore les annotations de type. Pour vraiment les vérifier, installe un type checker. mypy est l'original ; pyright (utilisé par Pylance de VS Code) est plus rapide.

pip install mypy
mypy your_project/

Le premier passage fera remonter des erreurs à des endroits que tu n'avais pas réalisés. Travaille-les progressivement — # type: ignore fait taire une seule ligne quand tu dois avancer.

Les IDE modernes lancent le type checking en continu pendant que tu édites, donc la plupart du feedback arrive avant l'enregistrement.

Quand les annotations de type ne conviennent pas

  • Scripts d'exploration rapide. Les annotations ajoutent de la friction à du code qui vit une heure.
  • Code fortement dynamique. La métaprogrammation, les systèmes de plugins et motifs similaires dépassent souvent ce que le système de types peut décrire. Annote l'API externe et laisse l'intérieur libre.
  • Bibliothèques tierces sans types. Si une bibliothèque que tu importes n'a pas d'infos de type, Any fuit dans ton code. Bon — ce n'est pas à toi de l'annoter.

Pour tout ce qui est entre les deux, les annotations de type sont une petite habitude avec un gros retour. Le coût, c'est quelques frappes de plus par signature de fonction. Le retour, c'est moins de bugs, des refactos plus faciles et du code qui se documente lui-même.

Ensuite : modules et imports

Tu as maintenant tout l'outillage au niveau fonction — arguments, décorateurs, annotations de type. Ensuite, on regarde comment Python organise le code à travers les fichiers : modules, packages et système d'import.

Questions fréquentes

Que sont les annotations de type en Python ?

Les annotations de type sont des notes qui décrivent les types attendus de variables, paramètres de fonction et valeurs de retour. Python lui-même ne les applique pas à l'exécution — elles servent aux outils (IDE, linters, type checkers comme mypy ou pyright) et aux humains qui lisent le code.

Les annotations de type rendent-elles Python plus rapide ?

Non. L'interpréteur Python ignore les annotations de type à l'exécution. L'accélération est dans ta boucle de développement — moins de fautes de frappe repérées par les éditeurs, signatures de fonctions plus claires, refactorisations plus sûres.

Quand devrais-je ajouter des annotations de type ?

Ajoute-les aux signatures de fonctions publiques — paramètres et types de retour. Ajoute-les avec parcimonie dans les corps de fonction, seulement là où le type d'une variable n'est pas évident. Pour des scripts à usage unique, elles sont optionnelles. Pour du code partagé et des bibliothèques, elles se paient rapidement.

Apprendre à coder avec Coddy

COMMENCER