@dataclass
Generate __init__, __repr__, and __eq__ for a class automatically from its type-annotated fields.
@dataclass
class Name:
field: type
field_with_default: type = value
Purpose
@dataclass inspects a class’s type-annotated fields and generates the boilerplate almost every
data-holding class needs by hand otherwise: __init__, a readable __repr__, and a value-based
__eq__ — without writing any of the three yourself.
Example
from dataclasses import dataclass, field
@dataclass
class Book:
title: str
author: str
available: bool = True
@dataclass
class Library:
books: list[Book] = field(default_factory=list)
b = Book(title="Dune", author="Frank Herbert")
print(b) # Book(title='Dune', author='Frank Herbert', available=True)
print(b == Book("Dune", "Frank Herbert")) # True — compares field values, not identity
Behavior notes
- Fields are declared with a type annotation, in the order
__init__should accept them; a field with= valuebecomes optional with that default, the same rule ordinary function parameters follow (defaults must come after non-defaults). - A mutable default (a
list,dict, or another dataclass) cannot be written directly asbooks: list[Book] = []—@dataclassraises an error specifically to stop the mutable default argument trap before it happens. Usefield(default_factory=list)instead, which callslist()fresh for each new instance. @dataclass(frozen=True)makes instances immutable after construction — attempting to reassign a field raisesFrozenInstanceError, useful for values that should behave liketuplerather thanlist.- The generated
__eq__compares every field’s value; two instances with equal fields are==even though they’re different objects (isstill distinguishes them) — see__repr__and__eq__.
Common mistakes
- Writing
books: list = []as a dataclass field default — this raisesValueError: mutable default ... is not allowedat class-definition time, specifically to prevent the shared-object trap; the fix isfield(default_factory=list). - Reaching for a full class with a hand-written
__init__for a class that’s really just a labeled bundle of values —@dataclassremoves that boilerplate for exactly this common case. - Assuming
@dataclassmakes a class immutable by default — it doesn’t; passfrozen=Trueexplicitly if that’s wanted.
Implementation notes
@dataclass is a standard-library decorator, not a language keyword — the class it produces
behaves like any ordinary Python class afterward. Its behavior is defined by the library
documentation and identical across conforming implementations.