@dataclass, defaults & field(default_factory)

Data classes

Lesson 9 of 20 · 11 min · Module 3: Objects that behave

Many classes exist mainly to hold data. Writing __init__, __repr__, and __eq__ by hand for each of them is repetitive. @dataclass generates them for you.

Start this lesson →

Free. No installation: you write and run the code in your browser, and it is checked automatically.

By the end, you’ll be able to…

  • Define a dataclass
  • Choose safe defaults
  • Use generated equality and repr

The idea

Declare fields with type annotations. Fields with defaults must come after fields without. For a mutable default such as a list, use field(default_factory=list), so each object gets its own list. Methods work like in any class.

from dataclasses import dataclass, field

@dataclass
class Course:
    title: str
    lessons: int = 20
    tags: list = field(default_factory=list)

print(Course("Python"))

01What you get for free

@dataclass writes __init__ from the fields, a readable __repr__ such as Task(title='Write', priority=3, tags=[], done=False), and __eq__ that compares field values.

from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int

print(Point(1, 2) == Point(1, 2))
Output
True

02Mutable defaults, again

tags: list = [] would be shared between objects, the same trap as with function defaults. Python even refuses it for dataclasses; field(default_factory=list) creates a fresh list per object.

03Still a normal class

You can add methods, properties, and class variables. Use frozen=True in @dataclass(frozen=True) when objects must not change after creation.

Your turn

Create a dataclass Task with title (str), priority (int, default 3), tags (list, a new empty list for each task), and done (bool, default False). Add complete(), which sets done to True and returns the task, and add_tag(tag), which stores the tag in lowercase only once.

What the checks look for

  • Task is a dataclass with the right defaults
  • Each task has its own tag list
  • add_tag lowercases and avoids duplicates
  • complete() marks the task done and returns it; equality is automatic
Try it in the editor →

Take this with you

Use @dataclass for classes that mostly hold data; it removes boilerplate and bugs.

Go a little further

Add a class method Task.from_text("Buy milk !1") that parses the priority from the text.

Learn Python Intermediate for free

20 short lessons with real code and instant checks.

See the whole course →