3.3. Typing Annotations

3.3.1. Alias

  • Used to make types more readable

  • Since Python 3.12 type soft keyword

  • Since Python 3.12 PEP 695 - Type Parameter Syntax

Declaration:

>>> type data = int | float

Example:

>>> type number = int | float
>>>
>>> age: number = 10      # ok
>>> age: number = 10.5    # ok
>>> age: number = None    # error

3.3.2. 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 = 1337     # ok
>>> data = 1.337    # error

Example:

>>> data: int | float = 1337     # ok
>>> data: int | float = 1.337    # ok
>>> data: int | float = 'hello'  # error

Result of this expression would then be valid in isinstance() and issubclass():

>>> isinstance(1337, int|float)
True

3.3.3. Optional

  • Used to inform static type checker that the variable should be X or None

  • int | None == None | int

Declaration:

>>> data: int | None
>>>
>>> data = 1337  # ok
>>> data = None  # error

Example:

>>> number: int | None = 1337    # ok
>>> number: int | None = None    # ok
>>> number: int | None = 1.0     # error

Result of this expression would then be valid in isinstance() and issubclass():

>>> isinstance(1337, int|None)
True

3.3.4. 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 = 1337
>>> data: Final[int] = 1337
>>> data: Final[float] = 1.337
>>> data: Final[bool] = True
>>> data: Final[str] = 'hello'

Definition:

>>> pressure: Final[float] = 1013.25    # ok
>>> pressure = 1024.00                  # error

3.3.5. 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.3.6. Any

SetUp:

>>> from typing import Any

Declaration:

>>> x: Any
>>>
>>> x = 1           # ok
>>> x = 2.0         # ok
>>> x = 'one'       # ok
>>> x = [1,2,3]     # ok

Example:

>>> x: Any = 1
>>> x: Any = 'one'
>>> x: Any = None
>>> x: Any = [1,2,3]

3.3.7. Use Case - 0x01

>>> firstname: str = 'Mark'
>>> lastname: str = 'Watney'
>>> age: int | float = 42
>>> adult: bool = True
>>> group: Literal['users', 'staff', 'admin'] = 'users'
>>> job: str | None = None
>>> height: int | float | None = 178.0
>>> weight: int | float | None = None

3.3.8. Use Case - 0x02

>>> SECOND: Final[int] = 1
>>> MINUTE: Final[int] = 60 * SECOND
>>> HOUR: Final[int] = 60 * MINUTE
>>> DAY: Final[int] = 24 * HOUR

3.3.9. Further Reading

3.3.10. References

3.3.11. Assignments

Code 3.30. Solution
"""
* Assignment: Typing Annotations Union
* Complexity: easy
* Lines of code: 2 lines
* Time: 2 min

English:
    1. Declare proper types for variables
    2. Use union with | notation (pipe)
    3. Run doctests - all must succeed

Polish:
    1. Zadeklaruj odpowiedni typ zmiennych
    2. Użyj unii z notacją | (pionowej kreski)
    3. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> assert data == 0.0, \
    'Do not modify variable `data` value, just add type annotation'
"""

# Declare proper types for variables
# Use alias with | notation (pipe)
T = ...

# Do not modify lines below
data: T = 0
data: T = 0.0

Code 3.31. Solution
"""
* Assignment: Typing Annotations Optional
* Complexity: easy
* Lines of code: 2 lines
* Time: 2 min

English:
    1. Declare proper types for variables
    2. Use optional with | notation (pipe)
    3. Run doctests - all must succeed

Polish:
    1. Zadeklaruj odpowiedni typ zmiennych
    2. Użyj optional z notacją | (pionowej kreski)
    3. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> assert data is None, \
    'Do not modify variable `data` value, just add type annotation'
"""

# Declare proper types for variables
# Use alias with | notation (pipe)
T = ...

# Do not modify lines below
data: T = 1
data: T = None

Code 3.32. Solution
"""
* Assignment: Typing Annotations Any
* Complexity: easy
* Lines of code: 3 lines
* Time: 2 min

English:
    1. Declare proper types for variables
    2. Use `Any` type
    3. Run doctests - all must succeed

Polish:
    1. Zadeklaruj odpowiedni typ zmiennych
    2. Użyj typu `Any`
    3. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> assert a == 1, \
    'Do not modify variable `a` value, just add type annotation'
    >>> assert b == 1.0, \
    'Do not modify variable `b` value, just add type annotation'
    >>> assert c == 'one', \
    'Do not modify variable `data` value, just add type annotation'
"""

# Declare proper types for variables
# Use alias with | notation (pipe)
T = ...

# Do not modify lines below
a: T = 1
b: T = 1.0
c: T = 'one'

Code 3.33. Solution
"""
* Assignment: Typing Annotations Literal
* Complexity: easy
* Lines of code: 3 lines
* Time: 2 min

English:
    1. Declare proper types for variables
    2. Use `Literal` type
    3. Run doctests - all must succeed

Polish:
    1. Zadeklaruj odpowiedni typ zmiennych
    2. Użyj typu `Literal`
    3. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> assert a == 'user', \
    'Do not modify variable `a` value, just declare type annotation'
    >>> assert b == 'staff', \
    'Do not modify variable `b` value, just declare type annotation'
    >>> assert c == 'admin', \
    'Do not modify variable `c` value, just declare type annotation'
"""

# Declare proper types for variables
# Use alias with | notation (pipe)
T = ...

# Do not modify lines below
a: T = 'user'
b: T = 'staff'
c: T = 'admin'


Code 3.34. Solution
"""
* Assignment: Typing Annotations Final
* Complexity: easy
* Lines of code: 3 lines
* Time: 2 min

English:
    1. Declare proper types for variables
    2. Use `Final` type with proper subtype
    3. Run doctests - all must succeed

Polish:
    1. Zadeklaruj odpowiedni typ zmiennych
    2. Użyj typu `Final` z odpowiednim subtypem
    3. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> assert a == 1, \
    'Do not modify variable `a` value, just add type annotation'
    >>> assert b == 1.0, \
    'Do not modify variable `b` value, just add type annotation'
    >>> assert c == 'one', \
    'Do not modify variable `c` value, just add type annotation'
"""

# Declare proper types for variables
# Use `Final` type with proper subtype
a: ... = 1
b: ... = 1.0
c: ... = 'one'