Python Dataclasses
In this page:
from dataclasses import dataclass
@dataclass
class ClassName:
field1: type
field2: type = default_value
What is a Dataclass?
A dataclass is a class whose main job is holding structured data rather than complex behavior.
Adding the @dataclass decorator above a class definition automatically generates __init__, __repr__, and __eq__ for you based on the class's annotated fields, eliminating the boilerplate you'd otherwise hand-write for a simple data container.
Example: What is a Dataclass?
from dataclasses import dataclass
@dataclass # auto-generates __init__, __repr__, and __eq__
class Point:
x: int
y: int
p = Point(1, 2)
print(p)
Default Values
Assigning a default value to a field (e.g. count: int = 0) means callers can omit that argument entirely when constructing an instance, and Python fills it in automatically.
This works exactly like a normal function's default arguments, since @dataclass builds its __init__ the same way you would by hand.
Example: Default Values
from dataclasses import dataclass
@dataclass
class Counter:
count: int = 0 # default lets callers omit this argument
print(Counter()) # uses the default
print(Counter(5)) # overrides it
Type Hinting in Dataclasses
Every field in a dataclass must carry a type annotation -- it's how the decorator discovers which class attributes are actual data fields versus ordinary class-level code.
Beyond that mechanical requirement, the annotations double as documentation, making the shape of your data obvious from the class body alone.
Example: Type Hinting in Dataclasses
from dataclasses import dataclass
@dataclass
class Product:
name: str # type annotation required for every dataclass field
price: float
p = Product("Book", 9.99)
print(p)
Read-Only Dataclasses
Passing frozen=True to the decorator makes instances immutable after construction: any attempt to reassign an attribute raises a FrozenInstanceError.
This is useful whenever you want value-object semantics, like using instances as dictionary keys or guaranteeing a record can't be silently mutated elsewhere in the codebase.
Example: Read-Only Dataclasses
from dataclasses import dataclass, FrozenInstanceError
@dataclass(frozen=True) # instances become immutable after construction
class Point:
x: int
y: int
p = Point(1, 2)
try:
p.x = 5 # reassignment is not allowed
except FrozenInstanceError:
print("Cannot modify a frozen dataclass")
The field() Function
Using a mutable default like [] or {} directly as a field value is a trap borrowed from ordinary function defaults -- every instance would end up sharing the exact same list object.
The field(default_factory=list) pattern fixes this by calling the factory fresh for each new instance instead of reusing one shared object.
Example: The field() Function
from dataclasses import dataclass, field
@dataclass
class Cart:
items: list = field(default_factory=list) # fresh list per instance, not one shared list
a = Cart()
b = Cart()
a.items.append("apple")
print(a.items, b.items) # b.items is unaffected
- Using a mutable default such as
items: list = [], which raisesValueError; usefield(default_factory=list). - Placing a field without a default after one that has a default, which raises
TypeError. - Forgetting
@dataclass, so the class has no generated__init__andPoint(1, 2)fails.
Chapter Quiz — Complete all 12 topics to unlock
0/12 topics done
Complete these topics first: