What does from __future__ import annotation do?

In Python, the from __future__ import annotations statement changes the default behaviour of type annotations in function signatures. This feature was introduced in Python 3.7 and significantly impacts how type hints are treated.

By default, in Python 3.7 and earlier, when you use type annotations in function signatures, the annotations themselves are evaluated immediately. This can lead to circular dependency issues, especially when dealing with classes that refer to themselves in type annotations.

The from future import annotations statement changes this behaviour. When you include this statement at the beginning of your code, Python will delay the evaluation of type annotations until after the whole module has been parsed. This means you can use types defined later in the module, even if they are self-referential.

Here’s an example to illustrate the difference:

Without from future import annotations (Python 3.7 and earlier):

def foo(bar: List[foo]):
    pass  # This will raise a NameError in Python 3.7 and earlier

With from future import annotations (Python 3.7 and later):

from __future__ import annotations

def foo(bar: List[foo]):
    pass  # No NameError here, since annotations are delayed

In most cases, using from future import annotations is recommended when working with type hinting and annotations in function signatures, as it helps prevent issues related to forward references. It makes the code cleaner and more intuitive when defining types and annotations.

Starting from Python 3.10, the behaviour of from future import annotations is enabled by default, meaning you don’t need to include this statement explicitly. In Python 3.10 and later, annotations are treated as if from future import annotations were always in effect. This change was made to improve the usability of type hints, especially when dealing with circular references.

References: