Module 10 ยท Lesson 32

Type Hints and Static Analysis

๐Ÿ Pythonโฑ 13 min read๐Ÿ“– Modern Python

Type Hints

Python is dynamically typed, but type hints let you annotate expected types. They don't affect runtime behavior โ€” they're for documentation, IDE assistance, and static analysis tools like mypy.

# Basic type annotations (Python 3.5+) def greet(name: str) -> str: return f"Hello, {name}!" def add(a: int, b: int) -> int: return a + b def divide(a: float, b: float) -> float | None: # Python 3.10+ if b == 0: return None return a / b # Variable annotations x: int = 42 name: str = "Alice" items: list = [] # Modern type syntax (Python 3.9+ for built-ins, 3.10+ for |) def process(items: list[str]) -> dict[str, int]: return {item: len(item) for item in items} # Before 3.9, import from typing from typing import List, Dict, Optional, Tuple, Set def old_style(items: List[str]) -> Dict[str, int]: return {item: len(item) for item in items}

Common Type Annotations

from typing import Optional, Union, Any, Callable, Sequence # Optional โ€” can be None def find_user(id: int) -> Optional[str]: # str | None return "Alice" if id == 1 else None # Union โ€” multiple types def process(data: Union[str, bytes]) -> str: # str | bytes return data.decode() if isinstance(data, bytes) else data # Callable โ€” function type def apply(func: Callable[[int, int], int], a: int, b: int) -> int: return func(a, b) # Sequence โ€” ordered collection (list, tuple, string) def first(items: Sequence[int]) -> int: return items[0] # TypeVar โ€” generic types from typing import TypeVar T = TypeVar('T') def identity(x: T) -> T: return x # Return type is same as input type

Classes and TypedDict

from typing import TypedDict, Protocol from dataclasses import dataclass # TypedDict โ€” typed dictionary class UserDict(TypedDict): name: str age: int email: str def process_user(user: UserDict) -> str: return f"{user['name']} ({user['age']})" # Protocol โ€” structural typing (duck typing formalized) class Drawable(Protocol): def draw(self) -> None: ... def render(shape: Drawable) -> None: shape.draw() # Works with any object that has draw() # dataclass with type hints (already covered!) @dataclass class Point: x: float y: float

Running mypy

# pip install mypy # Check a file mypy my_module.py # Strict mode mypy --strict my_module.py # Common mypy settings in pyproject.toml: # [tool.mypy] # python_version = "3.11" # strict = true # ignore_missing_imports = true # Example errors mypy catches: def add(a: int, b: int) -> int: return a + b add("hello", "world") # mypy error: Argument 1 has incompatible type "str"; expected "int" result: int = add(1.5, 2.5) # mypy error: Incompatible types in assignment

Key Takeaways

Practice Exercises

  1. Add type hints to all functions in a previous project. Run mypy and fix all errors.
  2. Write a typed generic Stack[T] class using TypeVar.
  3. Create a TypedDict for an API response structure. Write a function that parses and returns it.
โ† Async/Await