Get one quick Python tip each week Weekly Python advice: one quick Python tip every week

# dataclasses 2 min. read Python 3.8—3.11
Share
Tags

Let's talk about dataclasses in Python.

## A minimal boilerplate class

This `Point` class represents a 2-dimensional point:

``````class Point:
"""A two-dimensional point."""

def __init__(self, x, y):
self.x = x
self.y = y

def __repr__(self):
return f"Point(x={self.x}, y={self.y})"
``````

This class accepts arguments (thanks to the initializer method):

``````>>> from point import Point
>>> p = Point(1, 2)
``````

And it has a friendly string representation (thanks to the `__repr__` method):

``````>>> p
Point(x=1, y=2)
``````

## Using the dataclass decorator

Instead of writing our `__init__` and `__repr__` method ourselves, we could use the `dataclass` decorator (from Python's dataclasses module) when defining our class.

The `dataclass` decorator requires us to define the attributes (and arguments) of our class with type hints:

``````from dataclasses import dataclass

@dataclass
class Point:
"""A two-dimensional point."""

x: float
y: float
``````

The resulting class is essentially equivalent to this:

``````class Point:
"""A two-dimensional point."""

def __init__(self, x: float, y: float) -> None:
self.x = x
self.y = y

def __repr__(self):
return f"Point(x={self.x}, y={self.y})"

def __eq__(self, other):
"""Return True if our point is equal to the other point."""
if not isinstance(other, Point):
return NotImplemented
return (self.x, self.y) == (other.x, other.y)
``````

It has an initializer and a nice string representation (just as before):

``````>>> from point import Point
>>> p = Point(1, 2)
>>> p
>>> Point(x=1, y=2)
``````

We can access `x` and `y` attributes (just as in our previous class):

``````>>> p.x
1
>>> p.y
2
``````

But we can also check equality between two `Point` objects:

``````>>> p == Point(1, 2)
True
``````

We get all of that for free thanks to the `dataclass` decorator.

## Making class objects immutable

To make our `Point` objects immutable, we could pass `frozen=True` to our `dataclass` decorator:

``````from dataclasses import dataclass

@dataclass(frozen=True)
class Point:
"""A two-dimensional point."""

x: float
y: float
``````

Now our `Point` objects are immutable which means we can't assign to their attributes:

``````>>> p = Point(1, 2)
>>> p.x = 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 4, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field 'x'
``````

## When should you use dataclasses?

Whenever you'd like to quickly create a class with a friendly interface (with a nice string representation and sensible equality checking), consider reaching for the `dataclass` decorator from Python's dataclasses module.

A Python Tip Every Week Need to fill-in gaps in your Python skills? I send weekly emails designed to do just that.