@dataclass

A decorator that generates __init__, __repr__, and __eq__ for a data-storing class, based on type-annotated fields.

Returns
The same class, with the generated methods added.
On this page

Example

#
Python
from dataclasses import dataclass, field

@dataclass
class Student:
    name: str
    world: int
    points: int = 0
    badges: list[str] = field(default_factory=list)

emma = Student("Emma", 7)
emma.points += 40
emma.badges.append("Start")

print(emma)
print(emma == Student("Emma", 7, 40, ["Start"]))
print(Student("Jack", 2))
Resultsaved result, you can check it
Student(name='Emma', world=7, points=40, badges=['Start'])
True
Student(name='Jack', world=2, points=0, badges=[])

Definition and usage

#

The @dataclass decorator from the dataclasses module removes repetitive code from classes that store data. You just list the fields with type annotations (name: str), and the decorator generates __init__ with parameters in the same order, a readable __repr__, and __eq__, which compares objects field by field.

Fields can have default values (points: int = 0), but fields without a default must come before them. You give a list, dictionary, or other mutable object as a default value through field(default_factory=list), so that every object gets its own copy. Put any extra steps after object creation, such as validation or computing a helper field, in the __post_init__ method.

The decorator’s parameters change the class’s behavior, for example frozen=True blocks changes to fields, and order=True adds < and > comparisons. The asdict() function turns an object into a dictionary, for example to save as JSON, and replace() creates a copy with some fields changed. Type annotations are not checked while the program runs; they serve editors and tools like mypy.

Syntax

#
Syntax
from dataclasses import dataclass, field

@dataclass
class Name:
    field_name: Type
    field_with_default: Type = value
    items: list[Type] = field(default_factory=list)

@dataclass(frozen=True, order=True)
class Other:
    ...

Parameters

#
  • frozen

    bool, default False

    When True, changing a field raises FrozenInstanceError, and objects can be dictionary keys and set elements.
  • order

    bool, default False

    Adds the <, <=, >, and >= operators, which compare fields in order, just like tuples.
  • slots

    bool, default False

    Creates the class with __slots__: objects use less memory, and assigning to a nonexistent field raises an error.
  • kw_only

    bool, default False

    Forces every field to be given by name when creating the object.

More examples

#
Immutable objects with sorting
Python
from dataclasses import dataclass, field

@dataclass(frozen=True, order=True)
class Result:
    points: int
    name: str = field(compare=False)

results = [Result(78, "Jack"), Result(92, "Emma"), Result(85, "Mia")]
print([r.name for r in sorted(results, reverse=True)])

best = max(results)
try:
    best.points = 100
except AttributeError as error:
    print(type(error).__name__, error)
Resultsaved result, you can check it
['Emma', 'Mia', 'Jack']
FrozenInstanceError cannot assign to field 'points'

field(compare=False) excludes the field from comparisons, so the results are sorted only by points.

Validation and a computed field in __post_init__
Python
from dataclasses import dataclass, field

@dataclass
class Exercise:
    number: str
    exp: int
    world: int = field(init=False)

    def __post_init__(self):
        if self.exp < 0:
            raise ValueError("EXP cannot be negative")
        self.world = int(self.number.split("_")[0])

task = Exercise("7_3", 15)
print(task.world)
print(task)
Resultsaved result, you can check it
7
Exercise(number='7_3', exp=15, world=7)
asdict() and replace()
Python
import json
from dataclasses import asdict, dataclass, replace

@dataclass
class Course:
    title: str
    modules: int
    premium: bool = False

python = Course("Python", 12)
advanced = replace(python, title="Advanced Python", premium=True)

print(advanced)
print(asdict(python))
print(json.dumps(asdict(advanced), ensure_ascii=False))
Resultsaved result, you can check it
Course(title='Advanced Python', modules=12, premium=True)
{'title': 'Python', 'modules': 12, 'premium': False}
{"title": "Advanced Python", "modules": 12, "premium": true}

Good practices

#
  • Create fields with mutable default values through field(default_factory=list). Writing badges: list = [] raises ValueError as soon as the class is defined.
  • Types in annotations are not checked, so Student(name=123, world="seven") creates an object without an error. For validation, use __post_init__ or the pydantic library.
  • Objects with frozen=True can be safely shared between parts of the program, because no one can change them by accident.

Related entries

#

Spotted a mistake or missing an example? Write to us.