Advanced · Lesson 16 of 18 · 18 min
The type system
Annotations, gradual typing, and what Python does not check.
- Annotate functions and data structures
- Use Optional, Union, TypeVar, and Protocol
- Know that CPython ignores annotations at runtime
Hints are for people and checkers
Python's types are gradual and optional. `def greet(name: str) -> str:` documents intent. CPython will still happily call `greet(42)` unless you run a checker (Pyright, mypy) or a runtime validator. Annotations are available as `typing.get_type_hints` and, from 3.10, can use `|` unions: `str | None`.
Start with public function signatures and data structures. Do not type every local. Prefer built-in generics: `list[int]`, `dict[str, float]`, `tuple[str, ...]`. `Any` is an escape hatch that disables checking — use it as a boundary, not a habit.
from typing import Sequence
def longest(items: Sequence[str]) -> str | None:
if not items:
return None
return max(items, key=len)
print(longest(["a", "alpha", "ab"]))
print(longest([]))
print(longest.__annotations__)Protocols are structural
A `Protocol` describes a shape: any object with those methods matches, without inheritance. This is typing for duck typing. `TypeVar` names a consistent placeholder so `def first(xs: list[T]) -> T` keeps the element type.
`TypedDict` types dictionaries with known keys. `Literal['asc', 'desc']` restricts to specific values. `cast` is a checker-only assertion — it does nothing at runtime.
from typing import Protocol, TypeVar
T = TypeVar("T")
def first(xs: list[T]) -> T:
return xs[0]
class Closeable(Protocol):
def close(self) -> None: ...
def shutdown(resource: Closeable) -> None:
resource.close()
class Handle:
def close(self) -> None:
print("closed")
shutdown(Handle())
print(first([10, 20]), first(["a", "b"]))Check yourself
Quiz
1.If you call a function with the wrong annotated type at runtime:
2.`str | None` means:
3.A Protocol matches:
Practice
Exercise
Write `pick(items: list[str], index: int) -> str | None` that returns the item at index, or None if the index is out of range. Negative indexes should work like Python lists.
Tutor
Ask a question about this lesson. Answers are generated on demand and capped so the session stays focused.