One of the best ways to enforce code quality in Python projects is to run mypy checks at commit stage and automatically in CI/CD pipeline. Let me explain why I recommend mypy.
Python is a dynamic programming language, meaning that you do not specify types for your variables but values in memory do have a type. So variable x can be both a number 123 and a string ‘abcd’ even within the same function. While it can be convenient not to specify types and reuse the same variable for multiple types, some patterns may hide serious errors.
Python 3 introduced type annotations, where developers can optionally specify types. For example
def my_function(x: int) → int:
return x+1
In this case it is clear that my_funcion accepts int and return an int. The compiler ignores this type annotation. However, tools like mypy take it into account and tracks if we ever pass non-int type to my_function.
Mypy is an optional static type checker for Python and it analyses the code, similar to what compiler language would do. Initially it started as a standalone Python variant but over time it has been rewritten as Python 3 checker instead.
I usually recommend to start using mypy or similar checker as early in the project as possible, so that the team writes quality code and gets used to mypy from day 1, or as early as practical.
When you use mypy on an existing project it can be quite painful to fix all the errors and put type annotations in all files. However, this exercise almost always fishes out a few very hard to find bugs.
This article reflects my personal views and opinions only, which may be different from the companies and employers that I am associated with.