What are variable annotations?

Variable annotations are just the next step from # type comments, as they were defined in PEP 484; the rationale behind this change is highlighted in the respective section of PEP 526.

So, instead of hinting the type with:

primes = []  # type: List[int]

New syntax was introduced to allow for directly annotating the type with an assignment of the form:

primes: List[int] = []

which, as @Martijn pointed out, denotes a list of integers by using types available in typing and initializing it to an empty list.

What changes does it bring?

The first change introduced was new syntax that allows you to annotate a name with a type, either standalone after the : character or optionally annotate while also assigning a value to it:

annotated_assignment_stmt ::=  augtarget ":" expression ["=" expression]

So the example in question:

   primes: List[int] = [ ]
#    ^        ^         ^
#  augtarget  |         |
#         expression    |
#                  expression (optionally initialize to empty list)

Additional changes were also introduced along with the new syntax; modules and classes now have an __annotations__ attribute (as functions have had since PEP 3107 -- Function Annotations) in which the type metadata is attached:

from typing import get_type_hints  # grabs __annotations__

Now __main__.__annotations__ holds the declared types:

>>> from typing import List, get_type_hints
>>> primes: List[int] = []
>>> captain: str
>>> import __main__
>>> get_type_hints(__main__)
{'primes': typing.List<~T>[int]}

captain won't currently show up through get_type_hints because get_type_hints only returns types that can also be accessed on a module; i.e., it needs a value first:

>>> captain = "Picard"
>>> get_type_hints(__main__)
{'primes': typing.List<~T>[int], 'captain': <class 'str'>}

Using print(__annotations__) will show 'captain': <class 'str'> but you really shouldn't be accessing __annotations__ directly.

Similarly, for classes:

>>> get_type_hints(Starship)
ChainMap({'stats': typing.Dict<~KT, ~VT>[str, int]}, {})

Where a ChainMap is used to grab the annotations for a given class (located in the first mapping) and all annotations defined in the base classes found in its mro (consequent mappings, {} for object).

Along with the new syntax, a new ClassVar type has been added to denote class variables. Yup, stats in your example is actually an instance variable, not a ClassVar.

Will I be forced to use it?

As with type hints from PEP 484, these are completely optional and are of main use for type checking tools (and whatever else you can build based on this information). It is to be provisional when the stable version of Python 3.6 is released so small tweaks might be added in the future.

Answer from Dimitris Fasarakis Hilliard on Stack Overflow
๐ŸŒ
Python documentation
docs.python.org โ€บ 3 โ€บ library โ€บ typing.html
typing โ€” Support for type hints
A variable annotated with C may accept a value of type C. In contrast, a variable annotated with type[C] (or deprecated typing.Type[C]) may accept values that are classes themselves โ€“ specifically, it will accept the class object of C.
๐ŸŒ
Python
typing.python.org โ€บ en โ€บ latest โ€บ spec โ€บ annotations.html
Type annotations โ€” typing documentation
annotation_expression ::= <Required> '[' annotation_expression ']' | <NotRequired> '[' annotation_expression ']' | <ReadOnly> '[' annotation_expression']' | <ClassVar> ('[' annotation_expression']')? | <Final> ('[' annotation_expression']')? | <InitVar> '[' annotation_expression ']' | <Annotated> '[' annotation_expression ',' expression (',' expression)* ']' | <TypeAlias> (valid only in variable annotations) | unpacked (valid only for *args annotations) | <Unpack> '[' name ']' (where name refers to an in-scope TypedDict; valid only in **kwargs annotations) | string_annotation (must evaluate to
๐ŸŒ
Mypy
mypy.readthedocs.io โ€บ en โ€บ stable โ€บ cheat_sheet_py3.html
Type hints cheat sheet - mypy 1.19.1 documentation
# For most types, just use the name of the type in the annotation # Note that mypy can usually infer the type of a variable from its value, # so technically these annotations are redundant x: int = 1 x: float = 1.0 x: bool = True x: str = "test" x: bytes = b"test" # For collections on Python 3.9+, the type of the collection item is in brackets x: list[int] = [1] x: set[int] = {6, 7} # For mappings, we need the types of both keys and values x: dict[str, float] = {"field": 2.0} # Python 3.9+ # For tuples of fixed size, we specify the types of all the elements x: tuple[int, str, float] = (3, "yes
๐ŸŒ
Python
peps.python.org โ€บ pep-0526
PEP 526 โ€“ Syntax for Variable Annotations | peps.python.org
Being able to omit the initial value allows for easier typing of variables assigned in conditional branches: sane_world: bool if 2+2 == 4: sane_world = True else: sane_world = False ยท Note that, although the syntax does allow tuple packing, it does not allow one to annotate the types of variables when tuple unpacking is used:
๐ŸŒ
Mypy
mypy.readthedocs.io โ€บ en โ€บ stable โ€บ type_inference_and_annotations.html
Type inference and type annotations - mypy 1.19.1 documentation
This often arises when creating an empty list or dictionary and assigning it to a new variable that doesnโ€™t have an explicit variable type. Here is an example where mypy canโ€™t infer the type without some help: l = [] # Error: Need type annotation for "l" In these cases you can give the type explicitly using a type annotation: l: list[int] = [] # Create empty list of int d: dict[str, int] = {} # Create empty dictionary (str -> int) Note ยท Using type arguments (e.g. list[int]) on builtin collections like list, dict, tuple, and set only works in Python 3.9 and later.
Top answer
1 of 2
100

What are variable annotations?

Variable annotations are just the next step from # type comments, as they were defined in PEP 484; the rationale behind this change is highlighted in the respective section of PEP 526.

So, instead of hinting the type with:

primes = []  # type: List[int]

New syntax was introduced to allow for directly annotating the type with an assignment of the form:

primes: List[int] = []

which, as @Martijn pointed out, denotes a list of integers by using types available in typing and initializing it to an empty list.

What changes does it bring?

The first change introduced was new syntax that allows you to annotate a name with a type, either standalone after the : character or optionally annotate while also assigning a value to it:

annotated_assignment_stmt ::=  augtarget ":" expression ["=" expression]

So the example in question:

   primes: List[int] = [ ]
#    ^        ^         ^
#  augtarget  |         |
#         expression    |
#                  expression (optionally initialize to empty list)

Additional changes were also introduced along with the new syntax; modules and classes now have an __annotations__ attribute (as functions have had since PEP 3107 -- Function Annotations) in which the type metadata is attached:

from typing import get_type_hints  # grabs __annotations__

Now __main__.__annotations__ holds the declared types:

>>> from typing import List, get_type_hints
>>> primes: List[int] = []
>>> captain: str
>>> import __main__
>>> get_type_hints(__main__)
{'primes': typing.List<~T>[int]}

captain won't currently show up through get_type_hints because get_type_hints only returns types that can also be accessed on a module; i.e., it needs a value first:

>>> captain = "Picard"
>>> get_type_hints(__main__)
{'primes': typing.List<~T>[int], 'captain': <class 'str'>}

Using print(__annotations__) will show 'captain': <class 'str'> but you really shouldn't be accessing __annotations__ directly.

Similarly, for classes:

>>> get_type_hints(Starship)
ChainMap({'stats': typing.Dict<~KT, ~VT>[str, int]}, {})

Where a ChainMap is used to grab the annotations for a given class (located in the first mapping) and all annotations defined in the base classes found in its mro (consequent mappings, {} for object).

Along with the new syntax, a new ClassVar type has been added to denote class variables. Yup, stats in your example is actually an instance variable, not a ClassVar.

Will I be forced to use it?

As with type hints from PEP 484, these are completely optional and are of main use for type checking tools (and whatever else you can build based on this information). It is to be provisional when the stable version of Python 3.6 is released so small tweaks might be added in the future.

2 of 2
61

Everything between : and the = is a type hint, so primes is indeed defined as List[int], and initially set to an empty list (and stats is an empty dictionary initially, defined as Dict[str, int]).

List[int] and Dict[str, int] are not part of the next syntax however, these were already defined in the Python 3.5 typing hints PEP. The 3.6 PEP 526 โ€“ Syntax for Variable Annotations proposal only defines the syntax to attach the same hints to variables; before you could only attach type hints to variables with comments (e.g. primes = [] # List[int]).

Both List and Dict are Generic types, indicating that you have a list or dictionary mapping with specific (concrete) contents.

For List, there is only one 'argument' (the elements in the [...] syntax), the type of every element in the list. For Dict, the first argument is the key type, and the second the value type. So all values in the primes list are integers, and all key-value pairs in the stats dictionary are (str, int) pairs, mapping strings to integers.

See the typing.List and typing.Dict definitions, the section on Generics, as well as PEP 483 โ€“ The Theory of Type Hints.

Like type hints on functions, their use is optional and are also considered annotations (provided there is an object to attach these to, so globals in modules and attributes on classes, but not locals in functions) which you could introspect via the __annotations__ attribute. You can attach arbitrary info to these annotations, you are not strictly limited to type hint information.

You may want to read the full proposal; it contains some additional functionality above and beyond the new syntax; it specifies when such annotations are evaluated, how to introspect them and how to declare something as a class attribute vs. instance attribute, for example.

๐ŸŒ
FastAPI
fastapi.tiangolo.com โ€บ python-types
Python Types Intro - FastAPI
Python has support for optional "type hints" (also called "type annotations"). These "type hints" or annotations are a special syntax that allow declaring the type of a variable.
๐ŸŒ
Python.org
discuss.python.org โ€บ ideas
Annotating a variable without specifying its type - Ideas - Discussions on Python.org
March 13, 2024 - Iโ€™ve been acquainting myself with Pythonโ€™s type annotations (after way too long being stuck with much older versions of Python), and they have inspired a lot of exciting applications in my code (in my case the codebase iโ€ฆ
Find elsewhere
๐ŸŒ
mypy
mypy.readthedocs.io โ€บ en โ€บ latest โ€บ cheat_sheet_py3.html
Type hints cheat sheet - mypy 1.20.0+dev.1d8ddd5949c3ce1af6ba5ef7adee841740a1691c documentation
See Type inference and type annotations for more details. # This is how you declare the type of a variable age: int = 1 # You don't need to initialize a variable to annotate it a: int # Ok (no value at runtime until assigned) # Doing so can be useful in conditional branches child: bool if age < 18: child = True else: child = False
๐ŸŒ
Python Course
python-course.eu โ€บ annotations โ€บ type-annotations-and-hints.php
1. Type Annotations And Hints | Annotations | python-course.eu
All kind of data types can be assigned to this variable name: programming_language = 42 programming_language = ('Python', 'C', 'C++') We will now demonstrate what Python offers to take care of these "type intentions", or as it is called in Python jargon "type hints", aka "type annotations".
๐ŸŒ
Medium
leapcell.medium.com โ€บ explaining-python-type-annotations-a-comprehensive-guide-to-the-typing-module-87d9e3599d59
Explaining Python Type Annotations: A Comprehensive Guide to the typing Module | by Leapcell | Medium
March 12, 2025 - TypeVar is an important tool in the typing module for creating generic functions or classes. By defining type variables, it is possible to write generic code that can handle multiple different types of data, thereby improving the reusability of the code...
๐ŸŒ
DEV Community
dev.to โ€บ dan_starner โ€บ using-pythons-type-annotations-4cfe
Using Python's Type Annotations - DEV Community
January 11, 2022 - Type Annotating is a new feature added in PEP 484 that allows adding type hints to variables. They are used to inform someone reading the code what the type of a variable should be expected.
๐ŸŒ
GitHub
google.github.io โ€บ pytype โ€บ developers โ€บ annotations.html
Type Annotations | pytype
As a first step, type annotations on a variable are converted to pytypeโ€™s abstract types, and then stored as the type of that variable in much the same way assignments are. Specifically, x = Foo() and x: Foo should both lead to the same internal type being retrieved for x when it is referred to later in the code. Python currently supports two kinds of annotation,
๐ŸŒ
Medium
medium.com โ€บ @bluebirz โ€บ well-documented-with-variable-type-annotation-docstring-735a76f77228
Well-documented with variable type annotation & Docstring | by bluebirz | Medium
January 28, 2025 - And here are examples of annotating variable types. Primitive types that is int, float, bool, and str are basic yet frequently used in daily life. We add colon : after a variable followed by its types. Return type is defined after ->. In some cases, we want to leave some arguments with default values. We give its value after =. If we are using python 3.10 or newer, we can use pipe ( | ) express types that a argument could be.
๐ŸŒ
Python
typing.python.org โ€บ en โ€บ latest โ€บ spec โ€บ special-types.html
Special types in annotations โ€” typing documentation
type[T] where T is a type variable is allowed when annotating the first argument of a class method (see the relevant section).
๐ŸŒ
LogRocket
blog.logrocket.com โ€บ home โ€บ understanding type annotation in python
Understanding type annotation in Python - LogRocket Blog
June 4, 2024 - To annotate the dictionary, we will use a TypedDict that was introduced in Python 3.8. It allows us to annotate the value types for each property with a class-like syntax: from typing import TypedDict class StudentDict(TypedDict): first_name: ...
๐ŸŒ
HackerNoon
hackernoon.com โ€บ type-annotation-in-python
Type Annotation In Python | HackerNoon
February 1, 2022 - Type Annotation are a quick way to validate the actual type of the variables or arguments that are being passed to the functions it is also called type hinting.
๐ŸŒ
Real Python
realpython.com โ€บ python-type-checking
Python Type Checking (Guide) โ€“ Real Python
July 15, 2024 - Recall that type annotations are regular Python expressions. That means that you can define your own type aliases by assigning them to new variables.
๐ŸŒ
Liora
liora.io โ€บ blog โ€บ typing and annotation in python: how does it work?
Typing and Annotation in Python: How does it work?
2 weeks ago - For example : This function, which ... as output, allows us to specify two annotations: The first annotation corresponds to the type of variable desired as argument, a: str....
๐ŸŒ
Python
peps.python.org โ€บ pep-0484
PEP 484 โ€“ Type Hints | peps.python.org
By default generic types are considered invariant in all type variables, which means that values for variables annotated with types like List[Employee] must exactly match the type annotation โ€“ no subclasses or superclasses of the type parameter (in this example Employee) are allowed.