@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 = value becomes 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 as books: list[Book] = [] — @dataclass raises an error specifically to stop the mutable default argument trap before it happens. Use field(default_factory=list) instead, which calls list() fresh for each new instance.
  • @dataclass(frozen=True) makes instances immutable after construction — attempting to reassign a field raises FrozenInstanceError, useful for values that should behave like tuple rather than list.
  • The generated __eq__ compares every field’s value; two instances with equal fields are == even though they’re different objects (is still distinguishes them) — see __repr__ and __eq__.

Common mistakes

  • Writing books: list = [] as a dataclass field default — this raises ValueError: mutable default ... is not allowed at class-definition time, specifically to prevent the shared-object trap; the fix is field(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 — @dataclass removes that boilerplate for exactly this common case.
  • Assuming @dataclass makes a class immutable by default — it doesn’t; pass frozen=True explicitly 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.

Taught in these lessons

Related reference