from __future__ import annotations – la phrase qui ouvre l’avenir des annotations de type en Python
Mots-clés :
__future__,annotations,PEP 563,PEP 649,Python 3.7+
1. Pourquoi __future__ était-il nécessaire ?
Python a été conçu comme un langage à typage dynamique dès le début des années 1990. Cependant, avec l’essor des projets de grande envergure, le contrôle statique des types et la lisibilité du code sont devenus essentiels. Pour répondre à ces besoins, Python a introduit les annotations de type (type hints) et le module typing.
Mais les premières annotations étaient évaluées immédiatement à l’exécution, ce qui posait plusieurs problèmes.
| Problème | Exemple |
|---|---|
| Références circulaires | class A: passclass B(A): passUtiliser A directement dans une annotation provoque un NameError |
| Évaluation immédiate | from typing import Listdef f(x: List[int]) -> List[int]: ...La classe List doit être importée au moment de la définition de la fonction |
| Évaluation différée par chaîne | def f(x: "MyClass") -> "MyClass": ...Pour différer l’évaluation, il faut activer __future__ |
Pour résoudre ces problèmes, PEP 563 (Python 3.7) a introduit from __future__ import annotations.
2. Que signifie from __future__ import annotations ?
Définition : Depuis Python 3.7, cette directive permet de retarder l’évaluation de toutes les annotations de type en les stockant sous forme de chaînes de caractères.
Fonctionnement clé
- À la définition d’une fonction ou d’une méthode, les annotations sont conservées sous forme de chaînes.
- L’évaluation réelle se produit uniquement lorsqu’elle est requise (ex. via
typing.get_type_hints). - Même en présence de références circulaires, aucune erreur
NameErrorn’est levée.
Exemple d’utilisation
# sans __future__
class Node:
def __init__(self, value: int, next: 'Node' = None):
self.value = value
self.next = next
# avec __future__
from __future__ import annotations
class Node:
def __init__(self, value: int, next: Node | None = None):
self.value = value
self.next = next
Attention : Avec
__future__, toutes les annotations deviennent des chaînes. Si vous utiliseztyping.get_type_hints, le moduletypingévaluera automatiquement ces chaînes.
3. Évolutions après PEP 563
PEP 649 – redéfinition de l’évaluation différée
- Introduit dans Python 3.11.
- Même avec
__future__, l’évaluation différée ne se produit que lorsqu’elle est réellement nécessaire. typing.get_type_hintsutilise désormais un cache pour améliorer les performances.
Après Python 3.12
PEP 649est complètement implémenté ; l’évaluation différée devient encore plus efficace.from __future__ import annotationsdevient le comportement par défaut ; la déclaration explicite est souvent superflue.
4. Conseils pratiques
| Situation | Méthode recommandée | Raison |
|---|---|---|
| Références circulaires | from __future__ import annotations |
Évite NameError |
| Projets de grande taille | Déclaration __future__ + typing.get_type_hints |
Améliore les performances de vérification de type |
| Python 3.11+ | Omettre la déclaration | Le comportement par défaut est déjà différé |
| Annotations sous forme de chaîne | Utiliser typing.TYPE_CHECKING |
Évite les imports inutiles à l’exécution |
Exemple avec typing.TYPE_CHECKING
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .module_a import ClassA
class MyClass:
def method(self, obj: ClassA) -> None:
...
TYPE_CHECKING est True uniquement pour les analyseurs statiques, ce qui empêche l’importation à l’exécution.
5. Conclusion
from __future__ import annotationsrend possible l’évaluation différée des annotations de type, évitant ainsi les références circulaires et les erreurs d’exécution.- Depuis Python 3.11, l’évaluation différée est le comportement par défaut, rendant la déclaration souvent inutile.
- Pour les versions 3.7‑3.10 ou lorsque vous avez besoin d’une différenciation explicite, cette directive reste indispensable.
Astuce : Appliquez
__future__à l’ensemble de votre base de code pour garantir une cohérence. Couplé à un vérificateur de type statique (mypy, pyright, etc.), vous améliorez considérablement la qualité du code.
Ressources supplémentaires - PEP 563 : https://www.python.org/dev/peps/pep-0563/ - PEP 649 : https://www.python.org/dev/peps/pep-0649/ - Documentation officielle de mypy : https://mypy.readthedocs.io/en/stable/cheat_sheet.html
Articles connexes :
Aucun commentaire.