Learn how to avoid a frequent misuse and misunderstanding of typing.Optional.
According to the Python documentation, typing.Optional is a handy way to indicate that an object can be None. It’s a concise and elegant way to express this concept, but is it also crystal clear?
Let me rephrase this question: When you see the word “optional” in a Python context, what do you think it means? Imagine you see an argument called x that has the type of Optional[int]. The int part is rather clear, as most likely indicates an integer, but what does Optional mean? What’s your first thought?
Let’s consider the following two options:
I don’t have to provide a value of x because it’s optional.x value can be either int or None.
If you know Python type hinting well enough, you know option 2 is correct. But when you don’t… Maybe I’m wrong, but I cannot imagine any person who doesn’t know Python choosing option 2. It is option 1 that seems to make most sense. When I see information that something is optional, I think that… well, that it’s optional…
This issue leads to a frequent misuse of the typing.Optional type. This article aims to shed light on this misuse and guide you towards the correct understanding of this type.
These three type hints are equivalent:
from typing import Optional, Union
x: Union[str, None]x: Optional[str]x: str | None
Each of them conveys the same information: that x can be either a string or None. While perfectly valid, the first one (Union[str, None]) represents the early stages of type hinting in Python: it was the initial approach, but it’s not necessarily the preferred method nowadays. Then, Optional was added to the typing module, providing a more concise and straightforward way to express this concept. According to the mypy documentation:
You can use the Optional type modifier to define a type variant that allows None, such as Optional[int] (Optional[X] is the preferred shorthand for Union[X, None]).