3.6. Typing Nested

  • Before Python 3.9 you need from typing import List, Tuple, Set, Frozenset

  • Since Python 3.9: PEP 585 -- Type Hinting Generics In Standard Collections

>>> DATA = [
...     (5.8, 2.7, 5.1, 1.9, 'virginica'),
...     (5.1, 3.5, 1.4, 0.2, 'setosa'),
...     (5.7, 2.8, 4.1, 1.3, 'versicolor'),
... ]
>>>
>>> x = DATA[0][-1]
>>> x  
>>> # IDE don't know what type is species
>>> # and cannot give hints for autocompletion
>>> DATA = [
...     (5.8, 2.7, 5.1, 1.9, 'virginica'),
...     (5.1, 3.5, 1.4, 0.2, 'setosa'),
...     (5.7, 2.8, 4.1, 1.3, 'versicolor'),
... ]
>>>
>>> x: str = DATA[0][-1]
>>> x  
>>> # IDE knows exactly what type is species
>>> # and what methods hint for autocompletion

3.6.1. List of Lists

Declaration:

>>> data: list
>>> data: list[list]
>>> data: list[list[int]]

Example:

>>> data: list = [
...     [1, 2, 3],
...     [4, 5, 6],
...     [7, 8, 9]]
>>> data: list[list] = [
...     [1, 2, 3],
...     [4, 5, 6],
...     [7, 8, 9]]
>>> data: list[list[int]] = [
...     [1, 2, 3],
...     [4, 5, 6],
...     [7, 8, 9]]

3.6.2. List of Tuples

Declaration:

>>> data: list
>>> data: list[tuple]
>>> data: list[tuple[float, float, float, float, str]]

Example:

>>> data: list = [
...     (4.7, 3.2, 1.3, 0.2, 'setosa'),
...     (7.0, 3.2, 4.7, 1.4, 'versicolor'),
...     (7.6, 3.0, 6.6, 2.1, 'virginica'),
... ]
>>> data: list[tuple] = [
...     (4.7, 3.2, 1.3, 0.2, 'setosa'),
...     (7.0, 3.2, 4.7, 1.4, 'versicolor'),
...     (7.6, 3.0, 6.6, 2.1, 'virginica'),
... ]
>>> data: list[tuple[float, float, float, float, str]] = [
...     (4.7, 3.2, 1.3, 0.2, 'setosa'),
...     (7.0, 3.2, 4.7, 1.4, 'versicolor'),
...     (7.6, 3.0, 6.6, 2.1, 'virginica'),
... ]

3.6.3. List of Dicts

>>> data: list[dict] = [
...     {'features': [4.7, 3.2, 1.3, 0.2], 'label': 'setosa'},
...     {'features': [7.0, 3.2, 4.7, 1.4], 'label': 'versicolor'},
...     {'features': [7.6, 3.0, 6.6, 2.1], 'label': 'virginica'},
... ]
>>> data: list[dict[str, list[float] | str]] = [
...     {'features': [4.7, 3.2, 1.3, 0.2], 'label': 'setosa'},
...     {'features': [7.0, 3.2, 4.7, 1.4], 'label': 'versicolor'},
...     {'features': [7.6, 3.0, 6.6, 2.1], 'label': 'virginica'},
... ]

3.6.4. Aliases

Declaration:

>>> row = tuple[int, int, int]
>>> data: list[row]

Example:

>>> Iris = tuple[float, float, float, float, str]
>>>
>>> data: list[Iris] = [
...     (4.7, 3.2, 1.3, 0.2, 'setosa'),
...     (7.0, 3.2, 4.7, 1.4, 'versicolor'),
...     (7.6, 3.0, 6.6, 2.1, 'virginica'),
... ]
>>> features = list[float]
>>> label = str
>>>
>>> data: list[dict[str, features|label]] = [
...     {'features': [4.7, 3.2, 1.3, 0.2], 'label': 'setosa'},
...     {'features': [7.0, 3.2, 4.7, 1.4], 'label': 'versicolor'},
...     {'features': [7.6, 3.0, 6.6, 2.1], 'label': 'virginica'},
... ]

3.6.5. Unions

Declaration:

>>> a = tuple[str, str, str]
>>> b = tuple[int, int, int]
>>> c = tuple[float, float, float]
>>>
>>> data: list[a | b | c]
>>> header = tuple[str, str, str]
>>> row = tuple[int, int, int]
>>>
>>> data: tuple[header,row,...]

Example:

>>> Header = tuple[str, str, str, str, str]
>>> Row = tuple[float, float, float, float, str]
>>>
>>> DATA: tuple[Header,Row,...] = (
...     ('sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'species'),
...     (5.8, 2.7, 5.1, 1.9, 'virginica'),
...     (5.1, 3.5, 1.4, 0.2, 'setosa'),
...     (5.7, 2.8, 4.1, 1.3, 'versicolor'),
...     (6.3, 2.9, 5.6, 1.8, 'virginica'),
...     (6.4, 3.2, 4.5, 1.5, 'versicolor'),
...     (4.7, 3.2, 1.3, 0.2, 'setosa'),
... )

3.6.6. Use Case - 0x01

>>> GeographicCoordinate = tuple[float, float]
>>>
>>> locations: list[GeographicCoordinate] = [
...     (25.91375, -60.15503),
...     (-11.01983, -166.48477),
...     (-11.01983, -166.48477),
... ]

3.6.7. Use Case - 0x02

>>> data: list[list|tuple|set] = [
...    [1, 2, 3],
...    (4, 5, 6),
...    {7, 8, 9}]
>>> data: list[list[int] | tuple[int, ...] | set[int]] = [
...    [1, 2, 3],
...    (4, 5, 6),
...    {7, 8, 9}]
>>> row = list[int] | tuple[int, ...] | set[int]
>>>
>>> data: list[row] = [
...    [1, 2, 3],
...    (4, 5, 6),
...    {7, 8, 9}]

3.6.8. Further Reading

3.6.9. References

3.6.10. Assignments

Code 3.37. Solution
"""
* Assignment: Typing Annotations List of Tuple
* Complexity: easy
* Lines of code: 3 lines
* Time: 2 min

English:
    1. Declare proper types for variable
    2. Run doctests - all must succeed

Polish:
    1. Zadeklaruj odpowiedni typ zmiennej
    2. Uruchom doctesty - wszystkie muszą się powieść

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

"""

# Declare proper types for variable
data: ...

# Do not modify lines below
data = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]

Code 3.38. Solution
"""
* Assignment: Typing Annotations List of Tuple
* Complexity: easy
* Lines of code: 3 lines
* Time: 2 min

English:
    1. Declare proper types for variable
    2. Run doctests - all must succeed

Polish:
    1. Zadeklaruj odpowiedni typ zmiennej
    2. Uruchom doctesty - wszystkie muszą się powieść

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

"""

# Declare proper types for variable
data: ...

# Do not modify lines below
data = [
    (25.91375, -60.15503),
    (-11.01983, -166.48477),
    (-11.01983, -166.48477),
]

Code 3.39. Solution
"""
* Assignment: Typing Annotations List of Dict
* Complexity: easy
* Lines of code: 3 lines
* Time: 2 min

English:
    1. Declare proper types for variable
    2. Run doctests - all must succeed

Polish:
    1. Zadeklaruj odpowiedni typ zmiennej
    2. Uruchom doctesty - wszystkie muszą się powieść

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

    >>> assert data == [
    ...     {'features': [4.7, 3.2, 1.3, 0.2], 'label': 'setosa'},
    ...     {'features': [7.0, 3.2, 4.7, 1.4], 'label': 'versicolor'},
    ...     {'features': [7.6, 3.0, 6.6, 2.1], 'label': 'virginica'},
    ... ], \
    'Do not modify variable `data` value, just add type annotation'
"""

# Declare proper types for variable
data: ...

# Do not modify lines below
data = [
    {'features': [4.7, 3.2, 1.3, 0.2], 'label': 'setosa'},
    {'features': [7.0, 3.2, 4.7, 1.4], 'label': 'versicolor'},
    {'features': [7.6, 3.0, 6.6, 2.1], 'label': 'virginica'},
]