post_init runs after init in dataclasses for custom initialization.
1from dataclasses import dataclass, field23@dataclass4class User:5 name: str6 email: str7 _id: int = field(init=False, repr=False)8 is_active: bool = field(init=False, default=True)910 def __post_init__(self):11 # Called after __init__12 self._id = hash(self.name + self.email)13 self.name = self.name.title() # Normalize14 self.email = self.email.lower()1516user = User(name="alice", email="Alice@Example.COM")17print(user.name) # "Alice" (title case)18print(user.email) # "alice@example.com" (lowercase)19print(user._id) # Hash computed2021# Validation in __post_init__22@dataclass23class Age:24 value: int2526 def __post_init__(self):27 if self.value < 0 or self.value > 150:28 raise ValueError(f"Invalid age: {self.value}")2930# With inheritance31@dataclass32class Person:33 name: str3435 def __post_init__(self):36 self.name = self.name.strip()3738@dataclass39class Employee(Person):40 department: str4142 def __post_init__(self):43 super().__post_init__() # Call parent44 self.department = self.department.upper()
Use cases: