How to use post-init with dataclasses#
By default a class in Python has an __init__
method that is called when the class is instantiated. This method is used to initialize the class attributes. The example below shows this in action and how a variable is set by combining two other variables.
class Name:
def __init__(self, first, last):
self.first = first
self.last = last
self.full = f"{self.first} {self.last}"
def main():
name = Name(first="John", last="Doe")
print(name.full)
if __name__ == "__main__":
main()
By upgrading a class to a dataclass, the __init__
method is automatically created and the class attributes are automatically initialized. This means that the full
attribute is not set when the class is instantiated. The example below shows this in action and a common error that is raised when trying to setup the full
attribute as self
is not defined.
from dataclasses import dataclass
@dataclass
class Name:
first: str
last: str
full: str = f"{self.first} {self.last}"
def main():
name = Name(first="John", last="Doe")
print(name.full)
if __name__ == "__main__":
main()
To fix this, the __post_init__
method can be used. This method is called after the class is instantiated and can be used to set the full
attribute. The example below shows this in action. Besides dataclass
also field
is imported to be able to use the init=False
parameter to tell the dataclass to not initialize the full
attribute. Secondly the __post_init__
method is defined and the full
attribute is set by combining the first
and last
attributes.
from dataclasses import dataclass, field
@dataclass
class Name:
first: str
last: str
full: str = field(init=False)
def __post_init__(self):
self.full = f"{self.first} {self.last}"
def main():
name = Name(first="John", last="Doe")
print(name.full)
if __name__ == "__main__":
main()
Now the full
attribute is set when the class is instantiated and the output of the script is as expected for the first example:
John Doe