To understand the data classes of Python, let’s start with a simple example.
The following code defines a class named Point representing points in Euclidean space:
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
A=Point(2,3)
B=Point(2,3)
print(A==B)
# False
Unfortunately, it printed False even if the two points have the exact same location.
The reason is simple, we didn’t tell Python how to compare different Point instances when defining this class.
Therefore, we have to define the __eq__ method, which will be used to determine if two instances are equal or not:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
return self.x == other.x and self.y == other.y
A=Point(2,3)
B=Point(2,3)
print(A==B)
# True
The above code works as expected. However, it’s too much for just an obvious comparison.
Is there any chance that Python can become more intelligent and define the basic internal methods in advance for us? 🤔
Yes. Since Python 3.7, there is a new built-in decorator — @dataclass. We can define a data class as follows:
from dataclasses import dataclass
@dataclass
class Point:
x:int
y:int
A=Point(2,3)
B=Point(2,3)
print(A==B)
# True
As the above code shows, this class definition creates a Point class with two fields, x and y, and their type hints are both int.
We only defined two attributes of the Point class, nothing else. But why Python knows how to compare the points A and B properly this time?
In fact, the @dataclass decorator automatically generated several methods for the Point class, such as __init__ for initializing objects, __repr__ for generating string representations of objects, and __eq__ for comparing objects for equality.
Since the @dataclass decorator simplifies the process of creating data classes by automatically generating many special methods for us, it saves our time and effort in writing these methods and helps ensure that our data classes have consistent and predictable behavior.
Anytime you need to define classes that are primarily used to store data, don’t forget to leverage the power of the @dataclass decorator.