from __future__ import annotations – de sleutel tot de toekomst van type hints in Python
Keywords:
__future__,annotations,PEP 563,PEP 649,Python 3.7+
1. Waarom was __future__ nodig?
Python is sinds het begin van de jaren 90 een dynamisch getypeerde taal. Naarmate projecten groter werden, werd statische typecontrole en leesbaarheid steeds belangrijker. Om dit te ondersteunen introduceerde Python type hints via het typing-module.
Echter, de eerste type hints werden direct op runtime geïnterpreteerd, wat problemen veroorzaakte:
| Probleem | Voorbeeld |
|---|---|
| Cirkulair refereren | class A: passclass B(A): passGebruik van A in een type hint leidt tot NameError |
| Vroege evaluatie | from typing import Listdef f(x: List[int]) -> List[int]: ...De List moet al geïmporteerd zijn bij het definiëren van de functie |
| String lazy | def f(x: "MyClass") -> "MyClass": ...Om een type als string te laten uitstellen, is __future__ vereist |
Om deze problemen op te lossen, introduceerde PEP 563 (Python 3.7) from __future__ import annotations.
2. Wat is from __future__ import annotations?
Definitie: Een functie geïntroduceerd in Python 3.7 die alle type hints als strings opslaat, waardoor ze later kunnen worden geëvalueerd.
Kernwerking
- Bij het definiëren van functies/methodes worden type hints als strings opgeslagen.
- De daadwerkelijke evaluatie vindt plaats wanneer een type nodig is (bijv. via
typing.get_type_hints). - Cirkulair refereren werkt zonder
NameError.
Voorbeeld
# zonder __future__
class Node:
def __init__(self, value: int, next: 'Node' = None):
self.value = value
self.next = next
# met __future__
from __future__ import annotations
class Node:
def __init__(self, value: int, next: Node | None = None):
self.value = value
self.next = next
Let op: Met
__future__worden alle type hints strings, dus functies zoalstyping.get_type_hintsevalueren automatisch de strings.
3. Veranderingen na PEP 563
PEP 649 – herdefinitie van lazy evaluatie
- In Python 3.11 werd PEP 649 geïntroduceerd.
- Zelfs met
__future__gebeurt lazy evaluatie pas wanneer het echt nodig is. typing.get_type_hintsgebruikt een cache, wat de prestaties verbetert.
Na Python 3.12
- PEP 649 is volledig geïmplementeerd, waardoor lazy evaluatie nog efficiënter is.
from __future__ import annotationsis de standaard, dus meestal is een expliciete declaratie niet meer nodig.
4. Praktische tips
| Situatie | Aanbevolen aanpak | Reden |
|---|---|---|
| Cirkulair refereren | from __future__ import annotations |
Voorkomt NameError |
| Grote projecten | __future__ + typing.get_type_hints |
Verbeterde prestaties bij typecontrole |
| Python 3.11+ | Declaratie overbodig | Lazy evaluatie is standaard |
| String type hints | Gebruik typing.TYPE_CHECKING |
Voorkomt onnodige imports op runtime |
Voorbeeld: typing.TYPE_CHECKING gebruiken
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_CHECKINGisTruealleen voor statische typecheckers, dus er gebeurt geen import op runtime.
5. Afsluiting
from __future__ import annotationsmaakt lazy evaluatie van type hints mogelijk, waardoor cirkulaire referenties en runtime fouten worden voorkomen.- Vanaf Python 3.11 is lazy evaluatie de standaard, dus expliciete declaratie is meestal niet meer nodig.
- Het blijft echter nuttig voor Python 3.7–3.10 of wanneer expliciete lazy evaluatie gewenst is.
Tip: Voeg
__future__toe aan je hele codebase voor consistentie. Samen met statische typecheckers (mypy, pyright, etc.) verhoog je de codekwaliteit aanzienlijk.
Extra bronnen - PEP 563: https://www.python.org/dev/peps/pep-0563/ - PEP 649: https://www.python.org/dev/peps/pep-0649/ - mypy officiële documentatie: https://mypy.readthedocs.io/en/stable/cheat_sheet.html
Bekijk ook: onderstaande artikelen!
댓글이 없습니다.