Python Dataclass Practice Guide: Fields
A dataclass is a compact way to say that a class is mostly data. It generates the repetitive methods, but it is still a normal Python class. Understanding what it generates, and what it does not, prevents both boilerplate and false expectations.
Declare the fields
Write annotated class attributes. The decorator uses them to generate __init__, __repr__, and __eq__. Construction is positional unless you use keyword arguments. The generated repr is useful in logs and test failures.
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
print(Point(2, 3))A data-focused class
Place defaults in the right order
A field with a default can be omitted. A field without one must still be supplied, so it cannot follow a defaulted field in the class body. Reorder the fields or give the earlier field a default as well.
from dataclasses import dataclass
@dataclass
class User:
name: str
active: bool = True
print(User("Ada"))
print(User("Grace", False))Required then optional
Equality is field-based
Two dataclass instances compare equal when their fields compare equal, even if they are different objects. This is convenient in tests, but nested mutable fields still follow their own equality rules. Do not confuse equality with identity.
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
print(Point(1, 2) == Point(1, 2))
print(Point(1, 2) is Point(1, 2))Equal values, different objects
Convert with asdict
asdict recursively converts a dataclass instance into a dictionary. Lists, tuples, and nested dataclasses are converted too. It is handy for JSON-like output and assertions, but it is a copy, not a live view.
from dataclasses import dataclass, asdict
@dataclass
class Item:
name: str
price: float
print(asdict(Item("tea", 3.5)))A plain dictionary
Use frozen for value objects
frozen=True prevents attribute assignment after construction. That makes an instance safer to share and hash, but it does not deep-freeze nested mutable values. Use it for small value objects, not as a blanket replacement for every class.
from dataclasses import dataclass
@dataclass(frozen=True)
class Item:
name: str
price: float
item = Item("tea", 3.5)
print(item.price)An immutable record
Your practice checklist
- Annotate every field you want generated.
- Put required fields before fields with defaults.
- Expect __eq__ to compare field values.
- Use asdict for a plain dictionary copy.
- Use frozen=True for small immutable records.
Common questions
Do dataclasses validate types?
No. Annotations describe intent, but the generated __init__ does not enforce them at runtime.
Can a dataclass have methods?
Yes. It is a normal class; add methods, properties, or validation in __post_init__ when needed.
Is asdict a shallow copy?
It recursively converts dataclass values, but mutable objects inside the fields may still be shared. Inspect nested data when that matters.
Practice dataclasses
12 questions on fields, defaults, equality, asdict, and frozen instances.
Keep reading: