8.10. Function Type Annotation

8.10.1. Rationale

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

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

8.10.2. Return

def say_hello() -> str:
    return 'My name... José Jiménez'

8.10.3. Parameters

def add_numbers(a: int, b: int) -> int:
    return a + b

add_numbers(1, 2)
# 3

8.10.4. Union

from typing import Union


def add_numbers(a: Union[int, float], b: Union[int, float]) -> int:
    return int(a + b)


add_numbers(1, 2)       # 'Ok'
add_numbers(1.5, 2.5)   # 'Ok'
from typing import Union

def add_numbers(a: Union[int,float],
                b: Union[int,float]
                ) -> Union[int,float]:
    return a + b

add_numbers(1, 2)       # 'Ok'
add_numbers(1.5, 2.5)   # 'Ok'
from typing import Union

Number = Union[int, float]

def add_numbers(a: Number, b: Number) -> Number:
    return a + b

add_numbers(1, 2)       # 'Ok'
add_numbers(1.5, 2.5)   # 'Ok'

8.10.5. Optional

def find(text: str, what: str) -> Optional[int]:
    start_position = text.find(what)

    if start_position > 0:
        return start_position
    else:
        return None


find('Python', 'o')      # 4
find('Python', 'x')      # None

8.10.6. NoReturn

from typing import NoReturn


def stop() -> NoReturn:
    raise RuntimeError
from typing import Union, NoReturn


def valid_email(email: str) -> Union[NoReturn, str]:
    if '@' in email:
        return email
    else:
        raise ValueError('Invalid Email')


valid_email('jose.jimenez@nasa.gov')
# 'jose.jimenez@nasa.gov'

valid_email('jose.jimenez_at_nasa.gov')
# Traceback (most recent call last):
#     ...
# ValueError: Invalid Email

8.10.7. Literal

New in version Python: 3.8 See PEP 586

from typing import Literal


def open(filename: str, mode: Literal['r','w','a']) -> None:
    pass

open('data.csv', mode='w')  # Ok
open('data.csv', mode='r')  # Ok
open('data.csv', mode='a')  # Ok
open('data.csv', mode='x')  # Error

8.10.8. Annotations

def add_numbers(a: int, b: int) -> int:
    return a + b

add_numbers.__annotations__
# {'a': <class 'int'>,
#  'b': <class 'int'>,
#  'return': <class 'int'>}

8.10.9. Errors

  • Python will execute without even warning

  • Your IDE and mypy will yield errors

def add_numbers(a: int, b: int) -> int:
    return a + b


add_numbers('Jan', 'Twardowski')
# 'JanTwardowski'

8.10.10. More Information

Note

More information in Type Annotations and Type Checking