A dataclass generates methods such as initialization and equality from declared fields; frozen fields restrict normal assignment to those fields.
Python dataclasses: frozen fields require an immutable value model
Operation contract
The receipt record uses a tenant string, integer identifier and tuple of integer amounts. That component choice avoids the shallow-freeze problem of a mutable list field. The fixture shows value equality, tuple aggregation and rejection of ordinary reassignment to its identifier.
Failure and ownership boundary
Frozen is not a complete security barrier, and a frozen dataclass containing a list would still expose list mutation. Annotations also do not validate that arbitrary caller values have the declared runtime types. Construct validated records at Python JSON validation: reject duplicate members and non-integer amounts rather than treating generated initialization as a schema validator.
Working program
from dataclasses import dataclass, FrozenInstanceError
@dataclass(frozen=True)
class ReceiptBatch:
tenant: str
identifier: int
amounts: tuple[int, ...]
batch = ReceiptBatch("tenant-a", 41, (125, 75))
print(batch == ReceiptBatch("tenant-a", 41, (125, 75)))
print(sum(batch.amounts))
try:
batch.identifier = 42
except FrozenInstanceError:
print("field assignment rejected")Output
True
200
field assignment rejectedCosts and limits
Generated equality compares components and can cost O(n) for an n-element tuple. Freezing references does not recursively copy input; this fixture uses immutable components already.
Common Mistakes
- Frozen fields do not freeze a nested list.
- Annotations do not enforce a runtime schema.
Connected lessons
Python tuples: immutable containers can still contain mutable state, Python JSON validation: reject duplicate members and non-integer amounts, Java records: value carriers and defensive copies.
Related Python operation checks
Python hash and equality: immutable dictionary keys, Python slots: attribute layout without deep immutability.
Follow the integrity boundary
Python dataclasses.replace: a new record can retain old mutable fields.
