Union Type in Python: The Complete Guide (with Examples)

Updated: February 14, 2024 By: Guest Contributor Post a comment

Overview

In the dynamic landscape of Python programming, Union Types represent a significant leap towards static type checking, which in turn enhances code quality and readability. This guide will delve into Union Types in Python, demonstrating their utility with practical code examples.

Introduction to Union Type

Introduced in Python 3.10 as part of PEP 604, Union Types allow a parameter, variable, or return value to be typed as one of multiple options. Prior to 3.10, the typing.Union was used. Python 3.10 onwards, the union operation can be performed using the | operator.

Why Use Union Types?

  • Flexibility: It offers a syntax for functions or methods that can accept arguments of different types.
  • Readability: It makes the function signatures clearer and more understandable.
  • Type Checking: Enhances static type checking, helping prevent bugs.

Basic Syntax

from typing import Union # For Python 3.9 or earlier
# Python 3.10 and later
age_or_name: int | str = 'Peter'

Practical Examples

Example 1: Function Annotation

def greet(entity: str | int) -> str:
    if isinstance(entity, str):
        return f"Hello, {entity}!"
    elif isinstance(entity, int):
        return f"Hello, entity number {entity}!"

greet('Alice')
greet(123)

This function demonstrates how a variable can be of multiple types (str or int) and how the function’s behaviour changes depending on the type.

Example 2: Combining with Other Typing Features

from typing import List

def process_items(items: List[int | str]):
    for item in items:
        print(item)

This code shows the flexibility of Union Type when used in conjunction with generic types like List, enhancing the functionality to handle lists containing multiple type elements.

Example 3: In Type Hints

from typing import Optional

def nullable_string(s: Optional[str | int]):
    if s is not None:
        print(s)

Here, Optional is used to indicate that the variable s can either be of type str | int or None. This example further showcases the combination of Union Types with other typing constructs to represent complex type hints.

Advanced Usage

Union Types can also be integrated with other advanced features such as decorators, context managers, and abstract base classes, providing robust solutions to complex problems.

Using Union Types with Decorators

def type_checker(function):
    def wrapper(args): 
        if not isinstance(args, (int, str)):
            raise TypeError("Argument must be an int or str")
        return function(args)
    return wrapper

@type_checker
def hello(name: int | str):
    print(f"Hello, {name}!")

This decorator ensures that the argument passed to the decorated function is either an int or a str, showcasing a practical use case of Union Types in ensuring type safety.

Conclusion

Union Types in Python provide a sophisticated mechanism for developers to enforce type safety while maintaining the dynamic nature of the language. By incorporating Union Types into your code, you can benefit from improved readability, reduced bug rates, and better code quality overall.