MyPy Python static type hinting quick start

The benefits of Python static type checking and examples have already been given at length. In summary, Python static type checking enhances code quality now and in the future by defining (constraining) variables and functions (methods). Type hinting is compatible with Python 2 when the correct syntax is used, and MyPy can check type hinting in Python 2 mode.

assert vs. type hinting

Type enforcement can be done with assert, but type hinting is much more concise, flexible and readable than assert. Type hinting is being continually enhanced in CPython, numerous IDEs and type annotation checkers. With type hinting, the hint is right at the variable name (e.g. in the function declaration), while assert must occur in the code body.

Duck typing

MyPy static type checker considers the following to be interchangeable (valid) due to duck typing:

  • intfloat
  • floatcomplex

Note that str is not equivalent to bytes, one of the major benefits of Python 3.


pip install mypy


From the code project top level:

mypy . src

Note this command checks the package and not the top-level scripts, which must be manually specified. Configure file .mypy.ini to eliminate nuisance errors or otherwise configure mypy.

It takes a little practice to understand the messages. Where multiple types are accepted, for example, str and pathlib.Path use typing.Union. See the examples below.


Many times a function argument can handle more than one type. This is handled as follows:

from typing import Union
from pathlib import Path

def reader(fn: Union[Path, str]) -> str:
    fn = Path(fn).expanduser()

    txt = fn.read_text()

    return txt

Another case is where lists or tuples are used, the types within can be checked (optionally):

from typing import Union, Tuple, List

def reader(fn: Union[Path, str]) -> Tuple[float, float]:
    fn = Path(fn).expanduser()

    txt: List[str] = fn.read_text().split(',')

    latlon = (float(txt[0]), float(txt[1]))

    return latlon

Or perhaps dictionaries, where optionally types within can be checked:

from typing import Union, Dict, List, Any

def reader(fn: Union[Path, str]) -> Dict[str, float]:
    fn = Path(fn).expanduser()

    txt: List[str] = fn.read_text().split(',')

    params = {'lat': float(txt[0]),
              'lon': float(txt[1])}

    return params

If many value types are in the dictionary, you can use Union[] or simply Any e.g.

Dict[str, Any]

The default where no type is declared is Any, which basically means “don’t check this variable at this location in the code”.


enhanced mypy usage