3.1. Type Annotation Primitives¶
Also known as: "type annotations", "type hints", "gradual typing"
Types are not required, and never will be
Good IDE will give you hints
Types are used extensively in system libraries
More and more books and documentations use types
Introduced in Python 3.5
Since Python 3.5: PEP 484 -- Type Hints
Since Python 3.6: PEP 526 -- Syntax for Variable Annotations
Since Python 3.8: PEP 544 -- Protocols: Structural subtyping (static duck typing)
Since Python 3.9: PEP 585 -- Type Hinting Generics In Standard Collections
Since Python 3.10: PEP 604 -- Allow writing union types as X | Y
To type check use:
mypy
,pyre-check
,pytypes
Types are not required, and never will be. -- Guido van Rossum, Python initiator, core developer, former BDFL
It should be emphasized that Python will remain a dynamically typed language, and the authors have no desire to ever make type hints mandatory, even by convention. -- Python Software Foundation

Figure 3.14. Timeline of changes to type annotations from Python 3.0 to now 1¶
3.1.1. Int¶
Used to inform static type checker that the variable should be int
Declaration:
>>> data: int
>>> data: int = 1
>>> data: int = -1
Example:
>>> data: int
>>>
>>> data = 1 # ok
>>> data = -1 # ok
>>> data = 'hello' # error
3.1.2. Float¶
Used to inform static type checker that the variable should be float
Declaration:
>>> data: float
>>> data: float = 0.0
>>> data: float = 1.23
>>> data: float = -1.23
Example:
>>> data: float
>>>
>>> data = 1.0 # ok
>>> data = -1.0 # ok
>>> data = 'hello' # error
3.1.3. Str¶
Used to inform static type checker that the variable should be str
Declaration:
>>> data: str
>>> data: str = ''
>>> data: str = 'hello'
Example:
>>> data: str
>>>
>>> data = 'Mark' # ok
>>> data = 'Watney' # ok
>>> data = 'Mark Watney' # ok
3.1.4. Bool¶
Used to inform static type checker that the variable should be bool
Declaration:
>>> data: bool
>>> data: bool = True
>>> data: bool = False
Example:
>>> data: bool
>>>
>>> data = True # ok
>>> data = False # ok
>>> data = None # error
3.1.5. None¶
Used to inform static type checker that the variable should be None
Declaration:
>>> data: None
>>> data: None = None
Example:
>>> data: None
>>>
>>> data = True # error
>>> data = False # error
>>> data = None # ok
3.1.6. Union¶
Used to inform static type checker that the variable should either X or Y
Since Python 3.10: PEP 604 -- Allow writing union types as X | Y
int | str == str | int
Declaration:
>>> data: int | float
>>> data: int | float = 1337
>>> data: int | float = 1.337
Example:
>>> data: int | float
>>>
>>> data = 1337 # ok
>>> data = 1.337 # ok
>>> data = 'hello' # error
Result of this expression would then be valid in isinstance()
and issubclass()
:
>>> isinstance(1337, int|float)
True
3.1.7. Optional¶
Used to inform static type checker that the variable should be X or None
int | None == None | int
Declaration:
>>> data: int | None
>>> data: int | None = 1337
>>> data: int | None = None
Example:
>>> number: int | None
>>>
>>> number = 1337 # ok
>>> number = None # ok
>>> number = 1.0 # error
Result of this expression would then be valid in isinstance()
and issubclass()
:
>>> isinstance(1337, int|None)
True
3.1.8. Alias¶
Used to make types more readable
Declaration:
>>> data = int | float
Example:
>>> number = int | float
>>>
>>> age: number = 10 # ok
>>> age: number = 10.5 # ok
>>> age: number = None # error
3.1.9. Final¶
Used to inform static type checker the value should not change
Used to define constants
Since Python 3.8: PEP 591 -- Adding a final qualifier to typing
In Python there is not such thing as constants. All values can be changed
during the runtime. However using Final
we can achieve similar effect.
Static type checker will ensure that the value should not change during
the program.
SetUp:
>>> from typing import Final
Declaration:
>>> data: Final
>>> data: Final[int]
>>> data: Final[float]
>>> data: Final[bool]
>>> data: Final[str]
Definition:
>>> pressure: Final[float] = 1013.25 # ok
>>> pressure = 1024.00 # error
3.1.10. Literal¶
Since Python 3.8: PEP 586 -- Literal Types
Literal de-duplicates parameters
Equality comparisons of Literal objects are not order dependent
https://docs.python.org/3/library/typing.html#typing.Literal
SetUp:
>>> from typing import Literal
Declaration:
>>> data: Literal['one', 'two', 'three']
Problem:
>>> agency: str
>>>
>>> agency = 'NASA' # ok
>>> agency = 'ESA' # ok
>>> agency = 'Not existing' # ok
Solution:
>>> agency: Literal['NASA', 'ESA', 'POLSA']
>>>
>>> agency = 'NASA' # ok
>>> agency = 'ESA' # ok
>>> agency = 'Not existing' # error
3.1.11. Errors¶
Types are not Enforced
This code will run without any problems
Types are not required, and never will be
Although
mypy
,pyre-check
orpytypes
will throw error
>>> name: int = 'Mark Watney'
3.1.12. Use Case - 0x01¶
>>> firstname: str = 'Mark'
>>> lastname: str = 'Watney'
>>> age: int = 40
>>> adult: bool = True
>>> agency: Literal['NASA', 'ESA', 'POLSA'] = 'NASA'
>>> height: int | float = 185
>>> weight: int | float = 75.5
>>> job: str | None = None
3.1.13. Use Case - 0x02¶
>>> SECOND: Final[int] = 1
>>> MINUTE: Final[int] = 60 * SECOND
>>> HOUR: Final[int] = 60 * MINUTE
>>> DAY: Final[int] = 24 * HOUR
3.1.14. Further Reading¶
3.1.15. References¶
- 1
Briggs, J. Type Annotations in Python. Year: 2021. Retrieved: 2022-04-08. URL: https://towardsdatascience.com/type-annotations-in-python-d90990b172dc