Compute Derived Fields with @dataclass __post_init__ in Python
Compute derived fields like distance, area, and perimeter automatically in Python dataclasses using __post_init__ and field(init=False).
Python code
31 linesfrom dataclasses import dataclass, field
from math import sqrt
@dataclass
class Point:
x: float
y: float
distance: float = field(init=False)
def __post_init__(self):
self.distance = sqrt(self.x ** 2 + self.y ** 2)
@dataclass
class Rectangle:
width: float
height: float
area: float = field(init=False, repr=False)
perimeter: float = field(init=False)
def __post_init__(self):
self.area = self.width * self.height
self.perimeter = 2 * (self.width + self.height)
if __name__ == "__main__":
p = Point(3.0, 4.0)
r = Rectangle(5.0, 7.0)
print(f"Point: {p}")
print(f"Rectangle: {r}")
Output
Point: Point(x=3.0, y=4.0, distance=5.0)
Rectangle: Rectangle(width=5.0, height=7.0, perimeter=24.0)
How it works
The __post_init__ method runs after the generated __init__ and lets you compute fields that aren't passed in by the caller. With field(init=False), the derived attribute is excluded from the constructor signature, so Point(3.0, 4.0) works without specifying distance. Because area also sets repr=False, it's hidden from the string representation to keep output clean, while distance and perimeter are shown. This pattern keeps derived state consistent and avoids repetitive manual calculations.
Common mistakes
- Forgetting `field(init=False)` so derived fields must be passed manually.
- Using `repr=False` and then wondering why a field isn't shown in debug output.
- Mutating derived fields after creation, breaking the invariant computed in `__post_init__`.
Variations
- Use `functools.cached_property` for lazily computed fields that shouldn't be stored.
- Define a `classmethod` alternative constructor instead of computing in `__post_init__`.
Real-world use cases
- Calculating total price or tax from quantity and unit cost in an order dataclass.
- Deriving full name from first and last name fields in a user model.
- Computing bounding box area from coordinates for a geometry shape dataclass.
Sponsored
More from OOP & classes
- Add property getter setter validation in Python easy
- Binary Tree Inorder Traversal in Python easy
- Borg pattern shared state in Python medium
- Bridge Pattern in Python: Separate Abstraction from Implementation medium
- Composable Predicates with the &, |, ~ Operators in Python medium
- Composition over Inheritance: How to Build a Wallet Account in Python easy
Keep learning
Related tutorials and quizzes for this topic.