Python lets you write optional type hints where you can return either a specified type or None. This is a guide with some examples demonstrating different use cases.

For reference, here is what it looks like when a non-optional type hint for a string is specified in a Python function’s argument and return value:

Python
def example(string: str) -> str:
    return "Hello!"

Two Ways of Specifying Optional Type Hints

There are two ways to specify optional type hints.

You can import Optional from the typing module and then specify type hints as follows:

Python
from typing import Optional

def example(value: Optional[str]) -> Optional[str]:
    return value

As of Python 3.10, you can also use a shorthand notation, replacing Optional[str] with str | None. There is no import required:

Python
def example(value: str | None) -> str | None:
    return value

Both examples above are equivalent to each other. Both functions also accept None as a return type.

Examples

Here are some useful examples showing optional type hints using the typing module and the shorthand notation.

One Optional Type Hint

A single optional type hint for an integer as an argument and as a return value looks like this:

Python
from typing import Optional

def example(num: Optional[int] = 0) -> Optional[int]:
    return num

And this is what the shorthand notation looks like:

Python
def example(num: int | None = 0) -> int | None:
    return num

In the examples above, the num variable has to be an integer or None, and it has a default value of 0. The return type has to be an integer or None.

Two or More Optional Type Hints

To specify two or more optional type hints, we can import Union from the typing module.

In this example, the type hints indicate that either an integer, a string, or None can be assigned to the data input variable. The data variable has a default value of None.

The type hints also indicate that an integer, a string, or None can be returned.

Linters like mypy prefer an explicit None return value when None is a valid return type. That’s why the examples have return None instead of just return at the end of the function.

Python
from typing import Union

def example(data: Union[int, str, None] = None) -> Union[int, str, None]:
    return None

And this is what the shorthand notation would look like in Python 3.10+:

Python
def example(data: int | str | None = None) -> int | str | None:
    return None

References

I am no expert in Python, so please refer to the official documentation for more information: