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 Uniondef 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 Unionnumber = 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 Alias | Built-in Type |
---|---|
List | list |
Tuple | tuple |
Dict | dict |
Set | set |
Frozenset | frozenset |
Sequence | For list, tuple, and any other sequence data type. |
Mapping | For 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 Listratings: 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.