What you'll learn
Most classes exist just to hold data — a point, a product, a config. Writing __init__, __repr__, and __eq__ by hand for each is tedious and error-prone. Dataclasses generate all of it from a few type-annotated fields, and enums give you safe, named sets of choices.
By the end you'll be able to:
- Replace boilerplate classes with
@dataclass - Use defaults,
field(),frozen, andorder - Model fixed choices with
Enum - Choose between dataclass, namedtuple, and dict
The boilerplate problem
Here's a simple data holder written the manual way — notice how much ceremony it takes:
class Point: # the tedious, hand-written way
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point(x={self.x}, y={self.y})"
def __eq__(self, other):
return (self.x, self.y) == (other.x, other.y)That's a lot of repetitive code for "a thing with an x and a y." Dataclasses eliminate every line of it.
@dataclass
Decorate a class with @dataclass and list its fields as type-annotated class variables. Python generates __init__, __repr__, and __eq__ automatically:
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
p = Point(3, 4)
print(p) # __repr__ generated for you
print(p == Point(3, 4)) # __eq__ generated tooFrozen, defaults & ordering
Dataclasses are configurable. frozen=True makes instances immutable (great for hashable, safe-to-share values); order=True generates comparison methods so they sort. Give fields defaults directly — but for a mutable default like a list, use field(default_factory=list) to avoid the classic shared-default bug:
from dataclasses import dataclass, field
@dataclass(frozen=True, order=True) # immutable AND comparable
class Product:
name: str
price: float = 0.0 # a default value
tags: list = field(default_factory=list) # safe mutable default
a = Product("Pen", 2.5)
print(a.price, a.tags)
# a.price = 9 # FrozenInstanceError — can't mutate a frozen dataclass
print(Product("A", 1) < Product("B", 2)) # order=True enables <Watch out
tags: list = [] as a default — that single list would be shared by every instance. Always use field(default_factory=list) for mutable defaults. This is one of Python's most infamous gotchas.Enums
When a value must be one of a fixed set — a status, a direction, a suit — an enum is far safer than loose strings. It prevents typos (Status.ACTIVE is checked; "actve" is not), documents the valid options, and gives you autocomplete:
from enum import Enum
class Status(Enum):
PENDING = "pending"
ACTIVE = "active"
CLOSED = "closed"
s = Status.ACTIVE
print(s) # Status.ACTIVE
print(s.value) # active
print(s.name) # ACTIVE
print(Status("pending")) # look up by value
print(list(Status)) # iterate all membersTip
if status == "active". IntEnum works the same but its members also behave as integers, handy for flags and codes.Choosing a structure
Python offers several ways to bundle data. A quick guide:
| Use | When |
|---|---|
@dataclass | A record with named fields, methods, and possible mutation — your default choice |
namedtuple | A lightweight, immutable record; tuple-compatible and very memory-light |
TypedDict | You need a real dict (e.g. JSON) but want typed keys |
dict | Truly dynamic keys not known ahead of time |
Recap & quick check
Key takeaways
- @dataclass auto-generates __init__, __repr__, and __eq__ from type-annotated fields.
- frozen=True makes instances immutable; order=True makes them comparable/sortable.
- Use field(default_factory=list) for mutable defaults — never a bare [] default.
- Enums model a fixed set of named choices safely, replacing error-prone magic strings.
- Prefer a dataclass for records; namedtuple for light immutable records; TypedDict/dict for dict-shaped data.
Quick check
1. What does @dataclass generate for you?
2. How do you give a dataclass field a mutable default like a list?
3. What does frozen=True do?
4. Why use an Enum instead of strings?
5. Which is best for a simple record with named fields and behavior?
That wraps up Phase 3 — Object-Oriented Python! 🎉 Next we enter Phase 4 — Intermediate Python, starting with Module 18 — Modules & Packages.