Python Type Hints

Summary: in this tutorial, you’ll learn about the python type hints and how to use the mypy tool to check types statically.

Introduction to Python type hints

Some programming languages have static typing, such as C/C++. It means that you need to declare types of variables, parameters, and return values of a function upfront. The predefined types allow the compilers to check the code before compiling and running the program.

Python uses dynamic typing, in which variables, parameters, and return values of a function can be any type. Also, the types of variables can change while the program runs.

Generally, dynamic typing makes it easy to program and causes unexpected errors that you can only discover until the program runs.

Python’s type hints provide you with optional static typing to leverage the best of both static and dynamic typing.

The following example defines a simple function that accepts a string and returns another string:

def say_hi(name): return f'Hi {name}' greeting = say_hi('John') print(greeting)
Code language: Python (python)

Here’s the syntax for adding type hints to a parameter and return value of a function:

parameter: type -> type

For example, the following shows how to use type hints for the name parameter and return value of the say_hi() function:

def say_hi(name: str) -> str: return f'Hi {name}' greeting = say_hi('John') print(greeting)
Code language: Python (python)

Output:

Hi John
Code language: Python (python)

In this new syntax, the name parameter has the str type:

name: str
Code language: Python (python)

And the return value of the say_hi() function also has the type str:

-> str
Code language: Python (python)

Besides the str type, you can use other built-in types such as int, float, bool, and bytes for type hintings.

It’s important to note that the Python interpreter ignores type hints completely. If you pass a number to the say_hi() function, the program will run without any warning or error:

def say_hi(name: str) -> str: return f'Hi {name}' greeting = say_hi(123) print(greeting)
Code language: Python (python)

Output:

Hi 123
Code language: Python (python)

To check the syntax for type hints, you need to use a static type checker tool.

Using a static type checker tool: mypy

Python doesn’t have an official static type checker tool. At the moment, the most popular third-party tool is Mypy. Since Mypy is a third-party package, you need to install it using the following pip command:

pip instal mypy
Code language: Python (python)

Once installed mypy, you can use it to check the type before running the program by using the following command:

mypy app.py
Code language: Python (python)

It’ll show the following message:

app.py:5: error: Argument 1 to "say_hi" has incompatible type "int"; expected "str" Found 1 error in 1 file (checked 1 source file)
Code language: Python (python)

The error indicates that the argument of the say_hi is int while the expected type is str.

If you change back the argument to a string and run the mypy again, it’ll show a success message:

Success: no issues found in 1 source file
Code language: Python (python)

Type hinting & type inference

When defining a variable, you can add a type hint like this:

name: str = 'John'
Code language: Python (python)

The type of the name variable is str. If you assign a value that is not a string to the name variable, the static type checker will issue an error. For example:

name: str = 'Hello' name = 100
Code language: Python (python)

Error:

app.py:2: error: Incompatible types in assignment (expression has type "int", variable has type "str") Found 1 error in 1 file (checked 1 source file)
Code language: Python (python)

Adding a type to a variable is unnecessary because static type checkers typically can infer the type based on the value assigned to the variable.

In this example, the value of the name is a literal string so that the static type checker will infer the type of the name variable as str. For example:

name = 'Hello' name = 100
Code language: Python (python)

It’ll issue the same error:

app.py:2: error: Incompatible types in assignment (expression has type "int", variable has type "str") Found 1 error in 1 file (checked 1 source file)
Code language: Python (python)

Adding type hints for multiple types

The following add() function returns the sum of two numbers:

def add(x, y): return x + y
Code language: Python (python)

The numbers can be integers or floats. To set type hints for multiple types, you can use Union from the typing module.

First, import Union from typing module:

from typing import Union
Code language: Python (python)

Second, use the Union to create a union type that includes int and float:

def add(x: Union[int, float], y: Union[int, float]) -> Union[int, float]: return x + y
Code language: Python (python)

Here is the complete source code:

from typing import Union def add(x: Union[int, float], y: Union[int, float]) -> Union[int, float]: return x + y
Code language: Python (python)

Starting from Python 3.10, you can use the X | Y syntax to create a union type, for example:

def add(x: int | float, y: int | float) -> int | float: return x + y
Code language: Python (python)

Type aliases

Python allows you to assign an alias to a type and use the alias for type hintings. For example:

from typing import Union number = Union[int, float] def add(x: number, y: number) -> number: return x + y
Code language: Python (python)

In this example, we assign the Union[int, float] type an alias Number and use the Number alias in the add() function.

Adding type hints for lists, dictionaries, and sets

You can use the following built-in types to set the type hints for a list, dictionary, and set:

  • list
  • dict
  • set

If you type hints a variable as a list but later assign a dictionary to it, you’ll get an error:

ratings: list = [1, 2, 3] ratings = {1: 'Bad', 2: 'average', 3: 'Good'}
Code language: Python (python)

Error:

app.py:3: error: Incompatible types in assignment (expression has type "Dict[int, str]", variable has type "List[Any]") Found 1 error in 1 file (checked 1 source file)
Code language: Python (python)

To specify the types of values in the list, dictionary, and sets, you can use type aliases from the typing module:

Type AliasBuilt-in Type
Listlist
Tupletuple
Dictdict
Setset
Frozensetfrozenset
SequenceFor list, tuple, and any other sequence data type.
MappingFor dictionary (dict), set, frozenset, and any other mapping data type
ByteString bytes, bytearray, and memoryview types.

For example, the following defines a list of integers:

from typing import List ratings: List[int] = [1, 2, 3]
Code language: Python (python)

None type

If a function doesn’t explicitly returns a value, you can use None to type hint the return value. For example:

def log(message: str) -> None: print(message)
Code language: Python (python)

Summary

  • Use type hints and static type checker tools to make your code more robust.
Did you find this tutorial helpful ?