Study notes · 10% of the exam

Type Hints and Static Typing

Python type hints are checked by tools, not by the interpreter. Know how checkers solve generics and variance, how narrowing works, and where runtime libraries such as Pydantic step in.

Key points

  1. 1

    Annotations are stored in __annotations__ but never enforced by CPython; mypy, pyright or a runtime validator does the checking.

  2. 2

    In 3.13 function annotations are evaluated when the def runs; from __future__ import annotations stores strings, and 3.14 (PEP 649) evaluates lazily by default.

  3. 3

    Mutable containers are invariant (list, dict); read-only protocols such as Sequence and Mapping are covariant; callables are contravariant in their parameters.

  4. 4

    PEP 695 (3.12) adds def f[T], class Box[T] and type Alias = ..., with variance inferred from how T is used.

  5. 5

    TypeIs narrows both branches and requires a subtype; TypeGuard narrows only the true branch and allows unrelated types.

  6. 6

    Type decorators with ParamSpec (and Concatenate when they add or remove arguments) so the wrapped signature is preserved.

  7. 7

    Pydantic v2 validates at runtime: lax mode coerces values like "1" to 1, strict mode refuses them, and model_construct skips validation.

Common traps

  • A decorator typed Callable[..., Any] silently turns every decorated function into def (*Any, **Any) -> Any.

  • runtime_checkable isinstance checks only that attributes exist, not their types or signatures.

  • # type: ignore[code] with the wrong code hides nothing; name the exact error code mypy prints.

Test yourself on Type Hints and Static Typing

Ten questions, with the answer and explanation after each one.