Level: Advanced | Prerequisite: Intermediate Weeks 7-8 (OOP)
Learning Goals
- Learn the syntax of type hints (
int,str,list[int],Optional) - Perform static type checking with
mypy - Write data classes concisely with
@dataclass - Understand the pitfalls of
field(default_factory=list)
1. Basics of Type Hints
No impact at runtime, but greatly helps IDE autocompletion, static analysis, and documentation.
def greet(name: str, age: int = 20) -> str:
return f"{name}({age})"
count: int = 0
items: list[str] = []
2. typing Module
from typing import Optional, Union, Any, Callable
def find_user(uid: int) -> Optional[dict]:
"""Optional[X] = X | None"""
...
def parse(value: Union[str, int]) -> int:
"""str or int (in Python 3.10+ str | int)"""
...
handler: Callable[[int], str] = lambda x: str(x)
From Python 3.10+:
def find_user(uid: int) -> dict | None: ...
def parse(value: str | int) -> int: ...
3. Container Types
nums: list[int] = [1, 2, 3]
scores: dict[str, int] = {"Alice": 90}
pair: tuple[int, str] = (1, "a")
unique: set[int] = {1, 2, 3}
4. mypy
pip install mypy
mypy main.py
mypy --strict main.py #Strict mode
5. dataclass
Automatically generate __init__, __repr__, __eq__.
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
p = Point(1, 2)
print(p) #Point(x=1, y=2) — __repr__ automatic
print(p == Point(1, 2)) #True — __eq__ automatic
6. Dataclass Options
from dataclasses import dataclass, field
@dataclass
class Book:
title: str
author: str
tags: list[str] = field(default_factory=list) #Variable default value
price: float = 0.0
b = Book("Python", "Guido")
b.tags.append("language")
⚠️ tags: list[str] = [] is shared by all instances — never use it. Always use field(default_factory=list).
7. frozen dataclass
Immutable object. Hashable → can be used as set/dict keys.
@dataclass(frozen=True)
class Point:
x: int
y: int
p = Point(1, 2)
# p.x = 99 # FrozenInstanceError
{Point(1, 2)} # OK
Key Examples (examples/)
| File | Content |
|---|---|
01_type_hints.py |
Default type hint |
02_typing_module.py |
Optional, Union, Callable |
03_dataclass.py |
Dataclass default |
04_dataclass_advanced.py |
field, frozen |
⚠️ Common Mistakes
- Leave mutable default as is — use
field(default_factory=list) - Misinterpretation of
Optionalmeaning —Optional[int]=int | None. Not simply "optional argument" - Misunderstanding that type hints are validated at runtime — they're just hints. Runtime validation requires separate libraries like
pydantic
❓ FAQ
Q1. Do I have to add all type hints? A. Public APIs (function signatures) are highly recommended. Internal variables can be inferred sufficiently.
Q2. What's the difference between dataclass and pydantic.BaseModel?
A. dataclass is standard, pydantic is strong for runtime validation and serialization. If there's a lot of data processing, use pydantic.
Q3. What happens if I use Any?
A. mypy gives up checking. If possible, use a more specific type.
📝 Exercises (exercises/)
exercise1.md— adds type hints to intermediate codeexercise2.md—Book/Member/Loandataclassexercise3.md— 5 Optional/list/dict signatures
Next Week
Week 2. Decorators and Context Managers