Immutable data classes
Topics: Immutable data classes
Updated 2020-10-05
We have talked a lot about data classes in the last post. There is one further characteristic of data classes that I would like to study - immutability.
We can make a dataclass immutable such that it fulfills the same purpose as typing.NamedTuple
. To make a dataclass immutable we have to set frozen=True
when creating the class. Let’s see how we can change our DarkArmyMember
class from typing.NamedTuple
to a dataclass without losing its functionality.
Up to now our DarkArmyMember
class looked as follows:
class DarkArmyMember(NamedTuple):
name: str
birthyear: int
@property
def leader(self):
master_odon = DarkArmyMember('Master Odon', 1971)
return master_odon
def cast(self, spell: str):
print(f"{self.name}: {spell.incantation}!")
Once we instantiate a member of this class, we can’t change it anymore. Running
keres = DarkArmyMember('Keres Fulford', 1983)
keres.name = 'Adrien'
will raise AttributeError: can't set attribute
. When converting the class to a data class we can keep all our code.
@dataclass(frozen=True)
class DarkArmyMember:
name: str
birthyear: int
@property
def leader(self):
master_odon = DarkArmyMember('Master Odon', 1971)
return master_odon
def cast(self, spell: str):
print(f"{self.name}: {spell.incantation}!")
Let’s make sure that the class is immutable. Running
keres = DarkArmyMember('Keres Fulford', 1983)
keres.name = 'Adrien'
will raise dataclasses.FrozenInstanceError: cannot assign to field 'name'
. And we can still get a nice representation of the object without having to write our own __repr__()
method. Running print(keres)
will return NewDarkArmyMember(name='Keres Fulford', birthyear=1983)
.
Note: be careful with the datatypes of your fields. When a field contains a mutable datatype (for example a list) the field will stay mutable, even when setting frozen=True
(this also holds for namedtuples, by the way). So when you want to have a truly immutable class, make sure that all fields use immutable data types (for example a tuple instead of a list).
Further reading
Data classes have further functionalities that we haven’t discussed yet. If you want to know more about them, consider looking at PEP 557 or watching the PyCon 2018 talk on dataclasses.