The mypy utility is a static type checker for Python. It combines the benefits of dynamic typing and static typing. As you may know, the Python programming language is dynamically typed. So what does static type checking for Python mean? Read below to find out.

What is a type?

To store data used by a program, the system needs to know how much memory space is needed. To determine that, programming languages use types. A type matches a size of memory that must be allocated for the program to store the data. Some of the most common types are integer, float, and string.

A dynamically typed language checks types in the program during run time. Python has a “weak” type system, meaning the interpreter doesn’t enforce type checking.

A statically typed language checks types based on its analysis of the source code before the program runs. When a program passes a static type check, it is guaranteed to satisfy some set of type safety. Static type checking detects possible errors in the application code before run time. This is why mypy, which statically type checks Python applications, is useful.

Installation and running mypy

Since mypy is packaged in Fedora, installation is easy:

$ dnf install python3-mypy

Now, create a simple Python application to test and understand how mypy works.

class Person():
    def __init__(self,surname,firstname,age,job):
        self.surname = surname
        self.firstname = firstname
        self.age = age
        self.job = job

def display_doctors(persons):
    for person in persons:
        if person.job.lower()in['gp','dentist','cardiologist']:
            print(f'{person.surname} {}')

mike = Person('Davis', 'Mike', '45', 'dentist')
john = Person('Roberts', 'John', 21, 'teacher')
lee = Person('Willams', 'Lee', 'gp', 56)

display_doctors([mike, john, 'lee'])

Save this code snippet into a file named Next, run mypy against the test code:

$ mypy

Note mypy is permissive by default. When you run against the example no error is returned. This default is useful for an app with a large code base, since you can gradually introduce mypy into your project.

Adding type hints

Using the default Python 3.6 in Fedora 27 and up, you can use type hints to annotate your code. Then mypy can check the application against these type hints. Next, use an editor to add type hints to the display_doctors function in the example program:

from typing import List
def display_doctors(persons: List[Person]) -> None:
    for person in persons:
    if person.job.lower()in['gp','dentist','cardiologist']:
        print(f'{person.surname} {}')

The example adds the following hints:

  • List[Person] – This syntax expresses that the display_doctors function expects a list of Person object as an argument.
  • -> None – This syntax specifies that the function will return a None value.

Now, run mypy again:

$ mypy error: "Person" has no attribute "name" error: Argument 1 to "display_doctors" has incompatible type "Person"; expected "List[Person]" error: List item 2 has incompatible type "str"; expected "Person"

This results in some errors, which you can fix as follows:

  • First, in the print statement the program tries to access, which does not exist. Instead, the program should use person.firstname.
  • The second error occurs when the program calls display_doctors for the first time. The expected argument is a list of Person, but the example only passes a Person.
  • Finally, the last error is due to a mistake in the list of Person. Instead of adding the Person object lee to the list, the example app has added the string ‘lee’.

Here are the relevant fixes for the example program:

def display_doctors(persons: List[Person]) -> None:
    for person in persons:
    if person.job.lower()in['gp','dentist','cardiologist']:
        print(f'{person.surname} {person.firstname}')
display_doctors([mike, john, lee])

Edit the code as above, and run mypy again.

There are other errors in the program. Your exercise as a reader is to find them. Look at using type hints for the Person class. Try it by yourself first. If you want to check your work, the error free program is available on Github.


Hopefully this short introduction to mypy shows you some benefits for your code base. mypy makes it easier to maintain your code, and to read the application code. You can also catch typos and mistakes before your code runs. Note that mypy is also available for Python 2.7 applications. However, it uses a different syntax based on commenting.

Photo by Chris Ried on Unsplash