Python Typing: Enhancing Code Readability

PythonPythonBeginner
Practice Now

Introduction

In this tutorial, you will learn how to use the Python typing module to add type hints to your code. Type hints help make your code more readable and maintainable by explicitly indicating your functions' expected input and output types.

Basic Types

Type hints are a feature introduced in Python 3.5, and the typing module was added in Python 3.5.2 to provide a standard set of type annotations. Import the relevant types from the typing module to start using type hints.

from typing import List, Tuple, Dict

Type hints for basic types are straightforward. Just use the type itself as a hint.

Open the Python shell by typing the following command in the terminal.

python3
  1. Define a variable of type int, assign it a value, and print it.
age: int = 25
print(age) #Output: 25
  1. Define a variable of type float, assign a value, and print it.
temperature: float = 98.6
print(temperature) ## Output: 98.6
  1. Define a variable of type bool, assign it a value, and print it.
is_raining: bool = True
print(is_raining) ## Output: True
  1. Define a variable of type str, assign a value, and print it.
def greet(name: str) -> str:
    return f"Hello, {name}!"

print(greet("Alice")) ## Output: Hello, Alice!
  1. Define a function that takes two arguments of type int, multiplies them, and returns the result as an int.
def multiply(x: int, y: int) -> int:
    return x * y

result = multiply(5, 10)
print(result) ## Output: 50

Containers and Generics

Type hints for container types (like lists, dictionaries, and sets) can be more specific using generics.

Tips: The experiments with serial numbers 1-3 can be implemented in python shell, and the experiments with serial number 4 are implemented in WebIDE.

  1. Define a variable of type List[int], assign some values, and print it.
from typing import List
numbers: List[int] = [1, 2, 3, 4, 5]
print(numbers) ## Output: [1, 2, 3, 4, 5]
  1. Define a variable of type Dict[str, int], assign it some key-value pairs, and print it.
from typing import Dict
ages: Dict[str, int] = {"Alice": 25, "Bob": 30, "Charlie": 35}
print(ages) ## Output: {'Alice': 25, 'Bob': 30, 'Charlie': 35}
  1. Define a variable of type Tuple[str, int, float], assign it some values, and print it.
from typing import Tuple
person: Tuple[str, int, float] = ("Alice", 25, 5.7)
print(person) ## Output: ('Alice', 25, 5.7)
  1. Define a function that takes a list of integers as an argument and returns the result as a new set of integers.

Create a Project called list_to_set.py in the WebIDE and enter the following content.

from typing import List, Set

def get_unique_elements(elements: List[int]) -> Set[int]:
    return set(elements)

numbers = [1, 2, 2, 3, 4, 4, 4, 5]
unique_numbers = get_unique_elements(numbers)
print(unique_numbers)  ## Output: {1, 2, 3, 4, 5}

Use the following command to run the script.

python list_to_set.py

User-Defined Types

You can also use custom types and classes as type hints.

Tips: This experiment is implemented in WebIDE.

  1. Define a class Person with typed attributes name (str) and age (int) and a method get_summary that returns a string summarizing the person's name and age.

Create a Project called str_and_int_to_str.py in the WebIDE and enter the following content.

class Person:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age
    def get_summary(self) -> str:
        return f"{self.name} is {self.age} years old."

person1 = Person("Alice", 25)
print(person1.get_summary()) ## Output: Alice is 25 years old.

Use the following command to run the script.

python str_and_int_to_str.py
  1. Define a class Point with typed attributes x and y, both of type float and a method distance that takes another point as an argument and returns the distance between the two points.

Create a Project called other_to_float.py in the WebIDE and enter the following content.

import math

class Point:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y
    def distance(self, other: "Point") -> float:
        return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)

point1 = Point(0, 0)
point2 = Point(3, 4)
print(point1.distance(point2)) ## Output: 5.0

Use the following command to run the script.

python other_to_float.py

Type Aliases

Type aliases can create more readable type hints, especially for complex types.

Create a Project called type_aliases.py in the WebIDE and enter the following content.

from typing import List, Tuple

Coordinate = Tuple[float, float]
Path = List[Coordinate]

def get_distance(coord1: Coordinate, coord2: Coordinate) -> float:
    return ((coord1[0] - coord2[0])**2 + (coord1[1] - coord2[1])**2)**0.5

start = (0, 0)
end = (3, 4)
print(get_distance(start, end))  ## Output: 5.0

Use the following command to run the script.

python type_aliases.py

Optional and None

The Optional type can be used when a value can be either of a specific type or None.

  1. Define a function that takes an optional int argument, multiplies it by 2 if it is not None, and returns the result as an int or None if the input was None.

Create a Project called option_and_none_1.py in the WebIDE and enter the following content.

from typing import Optional

def double_or_none(number: Optional[int]) -> Optional[int]:
    if number is not None:
        return number * 2
    else:
        return None

result1 = double_or_none(5)
result2 = double_or_none(None)
print(result1, result2) ## Output: 10 None

Use the following command to run the script.

python option_and_none_1.py
  1. Define a class Person with a typed attribute address, either a valid address string or None.

Create a Project called option_and_none_2.py in the WebIDE and enter the following content.

from typing import Optional

class Person:
    def __init__(self, name: str, age: int, address: Optional[str]):
        self.name = name
        self.age = age
        self.address = address

person1 = Person("Alice", 25, "123 Main St")
person2 = Person("Bob", 30, None)
print(person1.name, person1.age, person1.address) ## Output: Alice 25 123 Main St
print(person2.name, person2.age, person2.address) ## Output: Bob 30 None

Use the following command to run the script.

python option_and_none_2.py

Callable

The Callable type is used to specify the type of a function or method.

Create a Project called callable.py in the WebIDE and enter the following content.

from typing import Callable

def apply_function(value: int, func: Callable[[int], int]) -> int:
    return func(value)

def double(x: int) -> int:
    return x * 2

print(apply_function(5, double))  ## Output: 10

Use the following command to run the script.

python callable.py

Typeddict

TypedDict allows you to create custom dictionaries with specific keys and value types.

Tips: TypedDict was introduced in Python 3.8, so you need to be running Python 3.8 or later to use it.

Here's an example:

Create a Project called typeddict.py in the WebIDE and enter the following content.

from typing import TypedDict

class PersonInfo(TypedDict):
    name: str
    age: int

def greet(person: PersonInfo) -> str:
    return f"Hello, {person['name']}! You are {person['age']} years old."

alice_info: PersonInfo = {"name": "Alice", "age": 30}
print(greet(alice_info))  ## Output: Hello, Alice! You are 30 years old.

Use the following command to run the script.

python typeddict.py

Newtype

NewType is a type hint from the typing module in Python that allows you to create a new type that is just a wrapper around an existing type. This can be useful for adding more semantic meaning to variables and function arguments.

Here's an example:

Create a Project called newtype.py in the WebIDE and enter the following content.

Then execute the following python script.

from typing import NewType

UserId = NewType("UserId", int)
OrderId = NewType("OrderId", int)

def get_order(order_id: OrderId) -> str:
    return f"Order with ID: {order_id}"

order_id = OrderId(123)
user_id = UserId(123)

print(get_order(order_id))  ## Output: Order with ID: 123

Use the following command to run the script.

python newtype.py

Static Type Checking

In Python, static type checking can be done using type hints and a static type checker like mypy. Type hints indicate the expected types of variables, function arguments, and return values. Here's an example:

First, install mypy.

pip install mypy

Here's an example:

Create a Project called mypy.py in the WebIDE and enter the following content.

def add_numbers(x: int, y: int) -> int:
    return x + y

result = add_numbers(2, 3)
print(result)

Then run mypy on your script.

mypy mypy.py

This will give you feedback on any type inconsistencies found in your code.

Summary

That's it! You now know how to use the Python typing module to add type hints to your code. Type hints can significantly improve code readability and maintainability, making it easier to work with larger codebases and collaborate with others.

Other Python Tutorials you may like