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).

Easy Python 3.7+ Aug 9, 2026 OOP & classes 12 views 0 copies

Python code

31 lines
Python 3.7+
from 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

stdout
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

  1. Use `functools.cached_property` for lazily computed fields that shouldn't be stored.
  2. 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

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from OOP & classes

Related tutorials and quizzes for this topic.