Python Dataclasses
A dataclass is a class that mainly holds data.
A plain class repeats itself
A plain class writes each routine method by hand. Most lines just store, show, and compare the same fields.
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"Dog(name={self.name!r}, age={self.age})"
def __eq__(self, other):
if not isinstance(other, Dog):
return NotImplemented
return (self.name, self.age) == (other.name, other.age)The dataclass version
@dataclass is a decorator: a tool that rewrites the class under it. Two field lines now do the work of the whole class above.
from dataclasses import dataclass
@dataclass
class Dog:
name: str
age: int
rex = Dog("Rex", 4)
print(rex)
print(rex == Dog("Rex", 4))Annotations declare the fields
An annotation is the type written after a name. Each annotated line becomes a field, taken in order.
buddy = Dog("Buddy", 2)
print(buddy.name)
print(buddy.age)Give a field a default
A field with a default can be left out. Fields with defaults must come after fields without them.
from dataclasses import dataclass
@dataclass
class Dog:
name: str
age: int = 1
pup = Dog("Pip")
print(pup)Turn equality off with eq=False
With eq=False, the decorator writes no __eq__ method. == then checks whether both sides are the same object.
from dataclasses import dataclass
@dataclass(eq=False)
class Dog:
name: str
age: int
first = Dog("Rex", 4)
second = Dog("Rex", 4)
print(first == second)
print(first == first)Example
from dataclasses import dataclass
@dataclass
class Dog:
name: str
breed: str
age: int = 1
rex = Dog("Rex", "Collie", 4)
pip = Dog("Pip", "Pug")
print(rex)
print(pip)
print(rex == Dog("Rex", "Collie", 4))
print(rex.name, rex.age)Key points
- Dataclass: a class that mainly holds data, with routine methods generated
- Use a dataclass when a class mainly stores named fields
- Use a dict when the keys arrive as outside data and change often
- Use a plain class when behavior matters more than the data
- eq=False: keeps the default identity check instead of field equality
In this example, Dog is a dataclass with three fields. name and breed are required, and age defaults to 1. rex passes all three values, so its age is 4. pip leaves age out, so the default 1 appears. The generated __repr__ prints each field with its name. The generated __eq__ compares rex with an equal Dog and returns True.
Note
An annotation does not enforce its type.
Python happily stores a string in an int field.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Python Playground
Exercise
What does @dataclass write for your class?