
Python has always been a dynamically typed language, which means you don’t have to specify data types for variables and function return values. PEP 484 introduced type hints – a way to make Python feel statically typed.
While type hints can help structure your projects better, they are just that – hints – and by default do not affect the runtime. However, there is a way to force type checks on runtime, and we’ll explore it today, after dialing in on some basics.
The article is structured as follows:
- Introduction to Type Hints
- Annotating Variables
- Exploring the typing Module
- Forcing Type Checks on Runtime
- Final Thoughts
Introduction to Type Hints
If you’re coming from a language like C or Java, specifying data types won’t feel new. But if you’re learning Python, almost zero online courses and books mention data type specification to keep things simple.
As the code base gets larger, type hints can help to debug and prevent some dumb mistakes. If you’re using an IDE like PyCharm, you’ll get a warning message whenever you’ve used the wrong data type, provided you’re using type hints.
Let’s start simple by exploring a function without type hints:
def add_numbers(num1, num2):
return num1 + num2
print(add_numbers(3, 5)) # 8
Nothing groundbreaking here, but I’ve declared a function like this on purpose, as adding numbers should work will both integers and floats. We’ll discuss later how to specify both with type hints.
Here’s how you can add type hints to our function:
- Add a colon and a data type after each function parameter
- Add an arrow (
->
) and a data type after the function to specify the return data type
Code-wise, you should make these changes:
def add_numbers(num1: int, num2: int) -> int:
return num1 + num2
print(add_numbers(3, 5)) # 8
Neat. If you’re working with a function that shouldn’t return anything, you can specify None
as the return type:
def add_numbers(num1: int, num2: int) -> None:
print(num1 + num2)
add_numbers(3, 5) # 8
Finally, you can also set a default value for the parameter, as shown below:
def add_numbers(num1: int, num2: int = 10) -> int:
return num1 + num2
print(add_numbers(3)) # 13
It’s all great, but what if we decide to call the add_numbers()
function with floating-point numbers? Let’s check:
def add_numbers(num1: int, num2: int) -> int:
return num1 + num2
print(add_numbers(3.5, 5.11)) # 8.61
As you can see, everything still works. Adding type hints has no runtime effect by default. A static type checker like mypy
can solve this "issue", but more about it later.
Let’s explore variable annotations next.
Variable Annotations
Just like with functions, you can add type hints to variables. While helpful, type hints on variables can be a bit too verbose for simple functions and scripts.
Let’s take a look at an example:
a: int = 3
b: float = 3.14
c: str = 'abc'
d: bool = False
e: list = ['a', 'b', 'c']
f: tuple = (1, 2, 3)
g: dict = {'a': 1, 'b': 2}
It’s a lot of typing for declaring a couple of variables. Things can get even more verbose, but more on that later.
You can also include type annotations for variables inside a function:
def greet(name: str) -> str:
base: str = 'Hello, '
return f'{base}{name}'
greet('Bob') # Hello, Bob
Next, let’s explore the built-in typing
module.
Exploring the typing
Module
Python’s typing
module can make data type annotations even more verbose. For example, you can specifically declare a list of strings, a tuple containing three integers, and a dictionary with strings as keys and integers as values.
Here’s how:
from typing import List, Tuple, Dict
e: List[str] = ['a', 'b', 'c']
f: Tuple[int, int, int] = (1, 2, 3)
g: Dict[str, int] = {'a': 1, 'b': 2}
Let’s see how to include these to a function. It will take a list of floats and returns the same list with the items squared:
def squre(arr: List[float]) -> List[float]:
return [x ** 2 for x in arr]
print(squre([1, 2, 3])) # 1, 4, 9
As you can see, it also works with integers. We’ll address that in a bit. Before doing so, let’s explore one important concept in type hints – the Union
operator. Basically, it allows you to specify multiple possible data types for variables and return values.
Here’s the implementation of the previous function:
from typing import Union
def square(arr: List[Union[int, float]]) -> List[Union[int, float]]:
return [x ** 2 for x in arr]
print(squre([1, 2, 3])) # 1, 4, 9
The function can now both accept and return a list of integers or floats, warning-free.
Finally, let’s explore how to force type checks on runtime.
Forcing Type Checks on Runtime
You can force type checks on runtime with mypy
(documentation). Before doing so, install it with either pip
or conda
:
pip install mypy
conda install mypy
Next, let’s make a Python file. I’ve named mine type_hints.py
:
def square(number: int) -> int:
return number ** 2
if __name__ == '__main__':
print(square(3))
print(square(3.14))
The function accepts the integer and squares it, at least according to type hints. Upon execution, the function is evaluated both with an integer and a float. Here’s what happens when using the default Python interpreter:

And now with mypy
:

As you can see, mypy
works as advertised, so feel free to use it when required.
Let’s wrap things up next.
Final Thoughts
Type hints in Python can be both a blessing and a curse. On the one hand, they help in code organization and debugging, but on the other can make the code stupidly verbose.
To compromise, I’m using type hints for function declaration – both parameter types and return values – but I generally avoid them for anything else, such as variables. In the end, Python should be simple to write.
What are your thoughts on type hints? Let me know in the comment section below.
Loved the article? Become a Medium member to continue learning without limits. I’ll receive a portion of your membership fee if you use the following link, with no extra cost to you.
Learn More
- Top 5 Books to Learn Data Science in 2021
- How to Schedule Python Scripts With Cron – The Only Guide You’ll Ever Need
- Dask Delayed – How to Parallelize Your Python Code With Ease
- How to Create PDF Reports With Python – The Essential Guide
- Become a Data Scientist in 2021 Even Without a College Degree
Stay Connected
- Follow me on Medium for more stories like this
- Sign up for my newsletter
- Connect on LinkedIn