Unions at run time
A union is a real object. isinstance accepts it, but not a parameterised generic such as list[int].
Hints for containers say what is inside: list[int], dict[str, int], tuple[int, str]. X | None means "an X, or nothing", and Sequence, Mapping, Iterable and Callable describe what a function needs without demanding one exact class.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 5 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Write first_or_none(items: list[int]) -> int | None that returns the first item or None for an empty list. Print the result for [7, 8] and [].
Write describe(value: int | str) -> str returning "number 5" or "text hi" using isinstance.
Write call_twice(fn: Callable[[int], int], x: int) -> int that returns fn(fn(x)) and call it with a lambda that adds 3 to 10.
Explain it without notes
How do you write the type of a list of integers, and which Python version made the plain list[int] form possible?
What does str | None mean, and how is it different from a parameter with a default value?
Why hint a function parameter as Iterable[int] instead of list[int]?
What is narrowing?
Why does a checker reject passing a list[int] to a function that takes list[float], yet accept it for Sequence[float]?
Expected output
Id is int | str
args: (<class 'int'>, <class 'str'>)
Union[int, str] == int | str -> True
origin of list[int]: <class 'list'> (<class 'int'>,)
True True False
TypeError: isinstance() argument 2 cannot be a parameterized generic
HI (nothing)
type(None): <class 'NoneType'>