Python Dataclass
On this page
Python Dataclass
The dataclasses
module, a feature introduced in Python 3.7, provides a way to create data classes in a simpler manner without the need to write methods.
A data class is a class typically containing mainly data, although there aren't really any restrictions. It is created using the new @dataclass
decorator.
from dataclasses import dataclass@dataclassclass DataClassCard:rank: strsuit: str
A data class is a regular Python class. The only thing that sets it apart is that it has basic data model methods like .__init__()
, .__repr__()
, and .__eq__()
implemented for you.
queen_of_hearts = DataClassCard('Q', 'Hearts')print(queen_of_hearts.rank)print(queen_of_hearts == DataClassCard('Q', 'Hearts'))
Default Values
It is easy to add default values to the fields of your data class.
from dataclasses import dataclass@dataclassclass Position:name: strlon: float = 0.0lat: float = 0.0
Type Hints
So far, we have not made a big fuss of the fact that data classes support typing out of the box. You have probably noticed that we defined the fields with a type hint: name: str
says that name
should be a text string (str
type).
from dataclasses import dataclassfrom typing import Any@dataclassclass WithoutExplicitTypes:name: Anyvalue: Any = 42
Adding Methods
You already know that a data class is just a regular class. That means that you can freely add your own methods to a data class.
from dataclasses import dataclassfrom math import asin, cos, radians, sin, sqrt@dataclassclass Position:name: strlon: float = 0.0lat: float = 0.0def distance_to(self, other):r = 6371 # Earth radius in kilometerslam_1, lam_2 = radians(self.lon), radians(other.lon)phi_1, phi_2 = radians(self.lat), radians(other.lat)h = (sin((phi_2 - phi_1) / 2)**2+ cos(phi_1) * cos(phi_2) * sin((lam_2 - lam_1) / 2)**2)return 2 * r * asin(sqrt(h))
More Flexible Data Classes
Some more advanced features like parameters to the @dataclass
decorator and the field()
function.
from dataclasses import dataclassfrom typing import List@dataclassclass PlayingCard:rank: strsuit: str@dataclassclass Deck:cards: List[PlayingCard]
Advanced Default Values
Data classes use something called a default_factory
to handle mutable default values. To use default_factory
(and many other cool features of data classes), you need to use the field()
specifier.
from dataclasses import dataclass, fieldfrom typing import ListRANKS = '2 3 4 5 6 7 8 9 10 J Q K A'.split()SUITS = '♣ ♢ ♡ ♠'.split()def make_french_deck():return [PlayingCard(r, s) for s in SUITS for r in RANKS]@dataclassclass Deck:cards: List[PlayingCard] = field(default_factory=make_french_deck)
The field()
specifier is used to customize each field of a data class individually. You will see some other examples later. For reference, these are the parameters field()
supports:
default
: Default value of the fielddefault_factory
: Function that returns the initial value of the fieldinit
: Use field in.__init__()
method? (Default isTrue
.)repr
: Use field inrepr
of the object? (Default isTrue
.)compare
: Include the field in comparisons? (Default isTrue
.)hash
: Include the field when calculatinghash()
? (Default is to use the same as forcompare
.)metadata
: A mapping with information about the field
from dataclasses import dataclass, field@dataclassclass Position:name: strlon: float = field(default=0.0, metadata={'unit': 'degrees'})lat: float = field(default=0.0, metadata={'unit': 'degrees'})
Immutable Data Classes
To make a data class immutable, set frozen=True
when you create it.
from dataclasses import dataclass@dataclass(frozen=True)class Position:name: strlon: float = 0.0lat: float = 0.0
Inheritance
You can subclass data classes quite freely.
from dataclasses import dataclass@dataclassclass Position:name: strlon: floatlat: float@dataclassclass Capital(Position):country: str
Optimizing Data Classes
Slots can be used to make classes faster and use less memory. Data classes have no explicit syntax for working with slots, but the normal way of creating slots works for data classes as well.
from dataclasses import dataclass@dataclassclass SimplePosition:name: strlon: floatlat: float@dataclassclass SlotPosition:__slots__ = ['name', 'lon', 'lat']name: strlon: floatlat: float