Skip to main content
  1. Posts/

Type union operator in Python 3.7+

·341 words·2 mins
Table of Contents

I’m a big fan of Python type hints. I try to use them whenever I can. Not only for static type checking with mypy. They also help document functions (sphinx has nice support for them) and force me to think about how I structure my functions.

One thing that bothers me, is that type hints can get quite verbose. Especially if you have multiple possible input types or optional values. For example, take this function that takes an int or a float as input:

1
2
3
4
5
# type_union.py
from typing import Union

def square(a : Union[int, float]):
    return a**2

Python 3.10 introduces a new type union syntax to make this a bit nicer to read. The piping operator (|) can be used to join multiple types:

1
2
3
4
# type_union_310.py

def square(a : int | float):
    return a**2

If you try to run this code in older versions of Python, it will raise this error:

1
>>> type_union_future.py:5: error: X | Y syntax for unions requires Python 3.10

It is a little known fact that the new type union syntax is also available in older versions of Python (3.7+) using a futures import! __future__ is a Python module part of the standard library that makes newer features available to older versions of Python.

If you add from __future__ import annotations to the top of your code:

1
2
3
4
5
# type_union_future.py
from __future__ import annotations

def square(a : int | float):
    return a**2

You can also use the new type union syntax in Python 3.7+! 🥳

Extra #

I was already aware that PEP-563 will introduce postponed evaluation of annotations. This will help deal with forward references. For example:

1
2
3
4
5
6
# forward_reference.py
from __future__ import annotations

class MyClass:
    def __constructor__(self) -> MyClass:
        pass

Without the futures import, this will be valid in mypy, but throws NameError: name 'MyClass' is not defined when trying to execute it. This has been available via the same from __future__ import annotations since Python 3.7.