Most classes analysts write are records: a few named fields and not much behavior. @dataclass writes the boilerplate for you. You list the fields with types, and it generates __init__, __repr__ and __eq__:
from dataclasses import dataclass, field
@dataclass
class Order:
id: str
total: float
tags: list = field(default_factory=list)
Fields can have defaults, but a list or dictionary default must use field(default_factory=list), so each object gets its own.
@dataclass(order=True) lets you sort objects; they compare field by field in the order written. @dataclass(frozen=True) makes objects read-only, which also lets you put them in sets and use them as dictionary keys.
__post_init__ runs after the generated __init__, the place to clean or check values. asdict(obj) turns a dataclass into a dictionary, ready for JSON or CSV.