A dict is the quickest way to hold a record, and the quickest way to misspell a key without anyone noticing. A @dataclass is one decorator and a list of fields, and in return Python writes the boring methods and catches the typos.
Before
order = {"id": "A-1001", "customer": "Ada", "total": 49.99}
order["totl"] = 59.99 # typo: a new key, not an update
print(order)
print(order == {"id": "A-1001", "customer": "Ada", "total": 49.99}){'id': 'A-1001', 'customer': 'Ada', 'total': 49.99, 'totl': 59.99}
FalseNothing complained. The bug surfaces much later, somewhere else.
After
from dataclasses import dataclass, field @dataclass class Order: id: str customer: str total: float = 0.0 items: list[str] = field(default_factory=list) a = Order("A-1001", "Ada", 49.99) b = Order("A-1001", "Ada", 49.99) print(a) print(a == b) a.items.append("keyboard") print(a.items, b.items)
Order(id='A-1001', customer='Ada', total=49.99, items=[]) True ['keyboard'] []
field(default_factory=list) gives each order its own list. A plain = [] would be shared by every order, the same trap as a default list in a function; dataclasses refuse it outright.
Freeze what shouldn't change
from dataclasses import dataclass, FrozenInstanceError @dataclass(frozen=True) class Reading: sensor: str celsius: float r = Reading("roof", 21.5) try: r.celsius = 99.0 except FrozenInstanceError as err: print("refused:", err)
refused: cannot assign to field 'celsius'
A frozen record can also be a dict key or a set member, because it can't change after it's hashed.
Why it works
The decorator reads the annotated fields and generates __init__, __repr__ and __eq__ from them. You get a readable print, comparison by value, and an editor that autocompletes order.customer instead of hoping you spell "customer" right.
When not to use it
For data that really is a mapping (JSON you pass straight through, counts keyed by word), keep the dict. If you need validation of incoming data, such as types checked at run time, a dataclass won't do that: its type hints are documentation, not checks.