🎓 Advanced · Topic 06
Type Hints & Static Analysis
Add type annotations to catch bugs before runtime, enable powerful IDE autocompletion, and make large codebases dramatically easier to maintain.
⏱ ~50 min
🔴 Advanced
🔒 Code quality
Basic Annotations
Type hints are completely optional at runtime — Python ignores them. They exist for static analysis tools like mypy and pyright, and for your IDE.
basics.py
# Variable annotations
name: str = "Alice"
age: int = 30
score: float = 98.5
# Function annotations
def greet(name: str, times: int = 1) -> str:
return (name + " ") * times
# Return None explicitly
def log(msg: str) -> None:
print(msg)
The typing Module
For complex types — collections, unions, optionals, callables — use the typing module (Python 3.9+ supports built-in generics like list[int] directly).
typing_module.py
from typing import Optional, Union, Callable, Any
# Optional = value or None
def find_user(user_id: int) -> Optional[str]:
return "Alice" if user_id == 1 else None
# Union = one of several types (Python 3.10+: str | int)
def parse(value: Union[str, int]) -> str:
return str(value)
# Callable[[arg_types], return_type]
def apply(func: Callable[[int], int], n: int) -> int:
return func(n)
# Python 3.9+ built-in generics
def total(nums: list[int]) -> int:
return sum(nums)
TypeVar & Generic Functions
Use TypeVar to write functions that are generic over a type — the return type mirrors the input type.
generics.py
from typing import TypeVar
T = TypeVar("T")
def first(items: list[T]) -> T:
return items[0]
x: int = first([1, 2, 3]) # mypy infers int
y: str = first(["a", "b"]) # mypy infers str
# Python 3.12+ new syntax
def last[T](items: list[T]) -> T:
return items[-1]
dataclasses — Type Hints + Boilerplate Elimination
@dataclass auto-generates __init__, __repr__, and __eq__ from annotated fields.
dataclasses_example.py
from dataclasses import dataclass, field
@dataclass
class Point:
x: float
y: float
z: float = 0.0
@dataclass(frozen=True) # immutable
class User:
name: str
email: str
tags: list[str] = field(default_factory=list)
p = Point(1.0, 2.0)
print(p) # Point(x=1.0, y=2.0, z=0.0)
u = User("Alice", "alice@example.com")
print(u) # User(name='Alice', email='alice@...', tags=[])
🛠️ Run mypy Install with pip install mypy then run mypy yourfile.py to catch type errors before execution. Use --strict for maximum coverage.