Type annotations and code quality
Be able to use type hints, linters and formatters for readable and safe code.
Prerequisites
- DPython — classes and objectsrequired
Intuition
Python runs without types, but type hints let tools find errors before the code runs — and document the API into the bargain.
def mean(values: list[float], weight: float | None = None) -> float: ...
The signature says everything: a list of numbers in, possibly a weight, a number out.
Where typing gives the most value:
- Public functions that others call.
- Data structures that pass between modules (dataclass, Pydantic, TypedDict).
- Interfaces to the outside world: API responses, configuration, file formats.
Where it gives the least: short scripts, notebooks, obvious local variables.
Code
from dataclasses import dataclass
from typing import Protocol, Literal
@dataclass(frozen=True)
class Result:
slug: str
score: float
method: Literal["rule", "llm", "runner"]
class Grader(Protocol): # structural typing: anything with the right shape will do
def grade(self, answer: str) -> Result: ...
def summarise(results: list[Result]) -> dict[str, float]:
if not results:
return {}
return {"mean": sum(r.score for r in results) / len(results),
"max": max(r.score for r in results)}
mypy src/ # type checking — finds errors without running the code
ruff check src/ # the linter: unused imports, undefined names, common mistakes
ruff format src/ # the formatter
What typing actually catches: None where a value is expected (the most common runtime bug in Python), the wrong argument order, fields that were renamed in a refactoring, and return values that do not match. Run mypy in CI, or the annotations rot.
Be realistic: start with --ignore-missing-imports and type the modules that others depend on. Full type coverage in an existing project is rarely worth it.
Mastery means
- Uses type hints on functions and data structures
- Runs mypy/ruff and interprets the errors
- Knows where typing gives the most value
Sign in to do the exercises and build your mastery up.