Type Hints and Type Checking in Python (49/100 Days of Python)

Martin Mirakyan
4 min readFeb 19, 2023
Day 49 of the “100 Days of Python” blog post series covering typing in Python

Python is a dynamically-typed language, which means that the type of a variable is determined at runtime, and not at the time of declaration. This can lead to some flexibility in your code, but also raises some questions about how to best handle types in a more robust and efficient way.

Type Hints for Variables

To declare a type for a variable in Python, simply add a colon followed by the type after the variable name:

name: str = 'John Doe'
age: int = 30

This way, if you try to assign a value of a different type to the variable, Python will hint you that it expected a different type with a message like Expected type 'str', got 'int' instead.

Type hints for variables are optional, but they can improve the readability and maintainability of your code.

Type Hints for Functions

The syntax for type hints in functions is similar to that of variables, but you’ll need to include the type hints in the function signature:

def repeat_message(message: str, times: int) -> str:
return message * times

Here, the message parameter is declared to be of type str, and the times parameter is declared to be of type int. The function's return type is declared to be str using the -> symbol.

Type hints for functions are optional, but they can make your code easier to understand, especially when working on larger projects with multiple contributors.

Type Hints for Classes

Type hints can also be used in classes, including for class variables and methods:

class Person:
name: str
age: int

def __init__(self, name: str, age: int):
self.name = name
self.age = age

def say_hello(self) -> None:
print(f'Hello, my name is {self.name}')

In this example, the name and age class variables are declared with type hints, and the __init__ method takes parameters with type hints. The say_hello method also has a return type hint of None. This means that it does not return anything. Type hints for classes can improve the understanding of the code and catch errors early in the development process.

Using Generic Types

In addition to basic types like str, int, and float, you can also use generic types in your type hints. For example, you might use a list of ints:

def sum_list(numbers: list[int]) -> int:
return sum(numbers)


def count_words(words: list[str]) -> dict[str, int]:
word_counts = {}
for word in words:
if word in word_counts:
word_counts[word] += 1
else:
word_counts[word] = 1
return word_counts

In this example, the sum_list function takes a list[int] as an argument and returns an int. The count_words function takes a list[str] and returns a dict[str, int], mapping words to their frequency in the list.

Working with the Typing Module

The typing module provides a number of additional type hints that can be useful in various situations. For example, you can use Union to specify that a parameter can accept values of multiple types:

from typing import Union

def add(a: Union[int, float], b: Union[int, float]) -> Union[int, float]:
return a + b

Yet, in the more recent versions of Python, a better alternative to using the Union type is to use the or oeprator |:

def add(a: int | float, b: int | float) -> int | float:
return a + b

In this example, the add function takes two parameters, a and b, which can be either int or float values. The return value can also be either an int or a float.

You can also use Optional to specify that a parameter is optional and can be None:

from typing import Optional

def say_hello(name: str, age: Optional[int] = None) -> None:
print(f'Hello, my name is {name}')
if age is not None:
print(f'I am {age} years old')

Similarly, you can use the or operator | to specify that the variable can be None as well:

def say_hello(name: str, age: int | None = None) -> None:
print(f'Hello, my name is {name}')
if age is not None:
print(f'I am {age} years old')

In this example, the age parameter is declared to be of type either int or None, which means it can be either an int or None. The default value is None, so the parameter is optional.

What’s next?

--

--

Martin Mirakyan

Software Engineer | Machine Learning | Founder of Profound Academy (https://profound.academy)