Introduction
Data classes (Python 3.7+) are a clean way to define classes that are mainly used
for storing data: configs, DTOs, models, request objects, etc.
They automatically generate __init__, __repr__, __eq__ and more.
1. Basic Data Class
from dataclasses import dataclass
@dataclass
class User:
username: str
age: int
u = User("Kaloyan", 12)
print(u.username, u.age)
You get an auto-generated __init__, nice __repr__, and comparisons.
2. Default Values
@dataclass
class Settings:
theme: str = "dark"
notifications: bool = True
s = Settings()
print(s.theme) # dark
3. Type Hints Are Required
Data classes rely on type hints. Every field should have a type annotation.
@dataclass
class Product:
name: str
price: float
in_stock: bool = True
4. Comparison Support
@dataclass
class Score:
value: int
a = Score(10)
b = Score(10)
print(a == b) # True
5. frozen=True (Immutable Objects)
@dataclass(frozen=True)
class Config:
api_key: str
timeout: int = 30
cfg = Config("ABC")
# cfg.timeout = 10 # ERROR: cannot assign to field
6. order=True (Sortable)
@dataclass(order=True)
class Player:
score: int
name: str
players = [
Player(100, "A"),
Player(250, "B"),
Player(150, "C"),
]
players.sort()
print(players) # sorted by score
7. field() for Advanced Options
from dataclasses import dataclass, field
from typing import List
@dataclass
class Session:
user: str
roles: List[str] = field(default_factory=list)
s = Session("Kaloyan")
s.roles.append("admin")
Use default_factory for lists/dicts to avoid shared mutable defaults.
8. Post-Init Logic
@dataclass
class Rectangle:
width: float
height: float
area: float = 0
def __post_init__(self):
self.area = self.width * self.height
r = Rectangle(4, 5)
print(r.area) # 20
9. asdict() and astuple()
from dataclasses import asdict, astuple
user = User("Kaloyan", 12)
print(asdict(user))
print(astuple(user))
10. Inheritance with Data Classes
@dataclass
class BaseUser:
username: str
@dataclass
class ProUser(BaseUser):
plan: str = "pro"
u = ProUser("Kaloyan")
print(u.username, u.plan)
11. Frozen + Hashable
Frozen data classes can be used as dict keys or in sets.
@dataclass(frozen=True)
class Point:
x: int
y: int
p = Point(1, 2)
points = {p}
12. When to Use Data Classes
- Configuration objects
- Lightweight models (for APIs, bots, tools)
- Replacing messy tuples/dicts with named fields
- Clean request/response types in Flask/FastAPI
13. When Not to Use Them
- Heavy behavior-focused classes (tons of methods)
- When you already use a full ORM model (e.g. SQLAlchemy)
Summary
@dataclassauto-generates boilerplate (__init__,__repr__,__eq__)frozen=True→ immutable, hashable objectsorder=True→ sortable instancesfield(default_factory=...)for lists, dicts__post_init__for computed fields- Perfect for clean, typed data containers in modern Python