Skip to content
Theory · Classes · lesson 9 of 11

Data classes

Imagine you draw the same parts on every new blueprint: how to fill in a card, how to label it, how to compare two. Only the names of the fields change. It is more convenient to list the fields and let a helper draw in the parts that never change.

That is exactly what a class that mostly holds data looks like. A Point class with __init__, __repr__ and __eq__ takes about ten lines, and x and y repeat in all three methods. Add a third coordinate, and all three need editing. For such classes, the standard library writes these methods:

Python
from dataclasses import dataclass


@dataclass
class Point:
    x: int
    y: int = 0


p = Point(1, 2)
print(p)  # Point(x=1, y=2)
print(p == Point(1, 2), Point(5))  # True Point(x=5, y=0)

Importing one name

You have already loaded whole modules. The line import math loads the module math, and its names are written with a dot: math.isclose.

The line from dataclasses import dataclass works differently. It takes the single name dataclass from the dataclasses module, and after that it is written without the module name.

A decorator for a class

dataclass is a decorator, except that it takes a class rather than a function. @dataclass over a class works as it does over a def: it equals the assignment Point = dataclass(Point) right after the class body.

The decorator adds methods to the class and returns the same class. A class it is applied to is called a data class.

Fields and annotations

The notation x: int is an annotation: a name, a colon and a type. In a data class, each annotated name in the class body becomes a field. The decorator reads the fields in order and writes three methods:

  • an __init__ with the same parameters;
  • a __repr__ of the form Point(x=1, y=2);
  • an __eq__ that compares the fields in order.

Let's look at what else the example shows:

  1. A value after = becomes a default value: Point(5) creates a point whose y is 0.
  2. Python does not check the annotation: Point("a") creates a point too. The type in it is written for the reader.
  3. The comparison == gives True only for instances of the same class: Point(1, 2) == (1, 2) is False.

This is where the helper analogy stops working. The decorator draws nothing as you watch: once, when the class is created, it adds ordinary methods to it. From then on, the class works as if you had written them yourself.

A data class is an ordinary class

The data class's __init__ stores each field in an instance attribute. So each point has its own x and y, even with a value in the class body. After p.x = 10, the point has a new coordinate. Methods are added to a data class the same way as to any class:

Python
@dataclass
class Item:
    name: str
    price: float
    qty: int = 1

    def total(self):
        return self.price * self.qty


cart = [Item("pen", 1.5, 4), Item("book", 12.0)]
print(sum(item.total() for item in cart))  # 18.0
print(cart[1])  # Item(name='book', price=12.0, qty=1)

__repr__ shows the field values through their own __repr__, which is why the string 'book' is in quotes.

Common mistake

A field without a default value is written after a field with one:

Python
@dataclass
class Item:
    name: str
    qty: int = 1
    price: float  # ✗
TEXT
TypeError: non-default argument 'price' follows default argument

In __init__, a parameter without a default value cannot follow a parameter with one, as in an ordinary function. The error comes when the class is created, before the first instance. Move the fields with default values to the end.

Key points

  • @dataclass writes __init__, __repr__ and __eq__ from the class's fields.
  • A field is an annotated name in the class body; a value after = is its default value.
  • Python does not check annotations, and fields without a default value come first.
  • from dataclasses import dataclass takes one name from a module, written without the module name.

Subscribe to take the course

The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.

Sign in another way