Let's talk about dataclasses in Python.
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)
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.
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'
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.
Need to fill-in gaps in your Python skills?
Sign up for my Python newsletter where I share one of my favorite Python tips every week.
Need to fill-in gaps in your Python skills? I send weekly emails designed to do just that.