One reason why Python is so easy to get started with is that it has dynamic types. You don’t have to specify the type of a variable, you just use variables as labels for containers of data. But in bigger projects, having types is helpful. If you have an undocumented function without types and maybe crappy variable naming, new developers will have a hard time. Luckily, variable annotations were added in Python 3.6 with PEP 526 🎉
This article is written in such a way that you can easily stop after the “mypy” section and take only a look at individual sections then.
Hello, Typed Annotated World!
So you can simply use the pattern
def some_function(param_name : typename) -> return_type_name:
... # whatever the function does
Having type annotations is nice, but you need to check them! The Python runtimes do not do that, no matter if you use CPython, pypy, or something more exotic.
Type Checking with mypy
Install mypy via
pip install mypy and run it:
$ mypy . --ignore-missing-imports
Success: no issues found in 1 source file
--ignore-missing-imports flag is necessary because otherwise you will get a lot of messages like this:
error: Skipping analyzing ‘setuptools’: found module but no type hints or library stubs
To make it more convenient, I usually add a
setup.cfg file in which I specify that I always want this flag to be applied:
Then you can
pip install pytest-mypy and make sure
mypy is always executed when you run
pytest by adding this section to your
addopts = --mypy
It is important to note that the Python community and also mypy assumes that you come from a non-type annotated codebase. They want to make it easy for you to switch to an annotated code and thus support gradual typing. However, this means that you might miss errors if you don’t annotate your code! Mypy has a lot of flags to help you to make the move. You don’t need to annotate everything.