CodeMIRAI
0 XP

Dataclasses

2 min read 6 runnable examples Quiz included

Many classes just hold data: a Point, a Product, a Student. Writing __init__, __repr__ and __eq__ by hand for each is repetitive. The @dataclass decorator writes them for you.

Before and after

By hand:

Python
class Product:
    def __init__(self, name, price, stock):
        self.name = name
        self.price = price
        self.stock = stock

    def __repr__(self):
        return f"Product(name={self.name!r}, price={self.price}, stock={self.stock})"

    def __eq__(self, other):
        return (self.name, self.price, self.stock) == (other.name, other.price, other.stock)

print(Product("Lamp", 27.75, 48))

With a dataclass:

Python
from dataclasses import dataclass

@dataclass
class Product:
    name: str
    price: float
    stock: int

lamp = Product("Lamp", 27.75, 48)
print(lamp)
print(lamp == Product("Lamp", 27.75, 48))
print(lamp.price)

You list the fields with type hints (name: str), and __init__, __repr__ and __eq__ are generated.

Default values

Python
from dataclasses import dataclass

@dataclass
class Task:
    title: str
    priority: int = 3
    done: bool = False

print(Task("Write tests"))
print(Task("Fix bug", priority=1))

Fields with defaults must come after fields without them.

Mutable defaults need field()

A list default would be shared by every instance (the same trap as with functions), so dataclasses refuse it. Use field(default_factory=...):

Python
from dataclasses import dataclass, field

@dataclass
class Course:
    name: str
    lessons: list = field(default_factory=list)

py = Course("Python")
js = Course("JavaScript")
py.lessons.append("Intro")
print(py, js)

Methods still work

Python
from dataclasses import dataclass

@dataclass
class Rectangle:
    width: float
    height: float

    def area(self):
        return self.width * self.height

print(Rectangle(3, 4).area())

Frozen and ordered dataclasses

frozen=True makes instances immutable (and usable as dictionary keys); order=True adds <, > and friends, comparing fields in order:

Python
from dataclasses import dataclass

@dataclass(frozen=True, order=True)
class Version:
    major: int
    minor: int
    patch: int = 0

versions = [Version(1, 10), Version(1, 2, 5), Version(0, 9)]
print(sorted(versions))
print(max(versions))
v = Version(2, 0)
v.major = 3
Finished this lesson?Mark it complete to earn +20 XP and move your progress on.