PEP 604 in 90 seconds — int | None replaces Optional[int]
The Optional import you never have to write again.
Before 3.10, every typed Python file had this litany at the top: ```python from typing import Optional, Union def find_user(uid: int) -> Optional[dict]: ... def parse(data: Union[str, bytes]) -> dict: ... ``` Two imports + verbose generics for the most common type-hinting cases. PEP 604 (Python 3.10, 2021) shipped the pipe operator at the type level: `int | None` and `str | bytes`. No imports needed.
It works **everywhere** types appear — function annotations, dataclasses, `cast()`, generics, AND **isinstance** (3.10+): ```python if isinstance(value, int | float): # legal — replaces (int, float) tuple return f"{value} is numeric" ``` Under the hood the pipe creates a `types.UnionType` instance. Pylance/Pyright/mypy all support it. Pydantic v2 reads it natively. Once your minimum Python is 3.10, you can `from typing import Optional, Union` your way to a leaner imports section.
from typing import Optional, Union, List
def find_user(uid: int) -> Optional[dict]:
"""Returns a user dict, or None if missing."""
...
def parse(data: Union[str, bytes]) -> dict:
...
# isinstance needed a tuple, not a Union
def classify(value):
if isinstance(value, (int, float)):
return "number"
if isinstance(value, (str, bytes)):
return "text"
return "other"
# Generics with unions got verbose fast
def merge(items: List[Union[int, str, None]]) -> List[Union[int, str]]:
return [x for x in items if x is not None]# No imports needed for the common cases.
def find_user(uid: int) -> dict | None:
"""Returns a user dict, or None if missing."""
...
def parse(data: str | bytes) -> dict:
...
# isinstance accepts the union form
def classify(value):
if isinstance(value, int | float):
return "number"
if isinstance(value, str | bytes):
return "text"
return "other"
# Generics stay readable
def merge(items: list[int | str | None]) -> list[int | str]:
return [x for x in items if x is not None]🎯 Predict the output
What does this print? `isinstance(value, A | B)` checks if value is an instance of A OR B.
def classify(value):
if isinstance(value, int | float):
return "number"
if isinstance(value, str | bytes):
return "text"
return "other"
print(classify(42))
print(classify("hi"))
print(classify(b"bytes"))
print(classify(3.14))
print(classify([1, 2, 3]))