Batu Lab NotesPractical developer guides

Create a frozen dataclass snapshot for a price quote

By Batu · English technical notes

Also published in our Blogger archive.

Create a frozen dataclass snapshot for a price quote

A quote often represents the price observed at a particular point in a workflow. A frozen dataclass is a useful way to express that its declared attributes should not be reassigned after construction. Here, PriceQuote stores a symbol, an integer price in cents, and a currency. Using cents avoids the binary floating-point representation issues that would be unrelated to the example.

@dataclass(frozen=True) generates the usual dataclass methods and prevents ordinary assignment to a field. The attempted assignment raises FrozenInstanceError, which is an AttributeError subclass, so the example catches that specific exception and asserts that the mutation was blocked. The equality assertion also shows that generated equality uses the declared field values for instances of the same dataclass type.

This is not a deep-immutability guarantee. If a frozen dataclass field refers to a mutable object, that referenced object can still be mutated; freezing mainly protects assignment and deletion of the dataclass fields themselves. Use immutable field values, or make defensive copies at the boundary, when a fully stable snapshot is needed. Dataclasses were added in Python 3.7, and frozen=True is available from that version.

The official dataclasses documentation describes generated equality, frozen instances, and FrozenInstanceError.

AI assistance disclosure: This article was drafted with AI assistance and should be reviewed for a project’s own data-model requirements.

from dataclasses import FrozenInstanceError, dataclass


@dataclass(frozen=True)
class PriceQuote:
    symbol: str
    cents: int
    currency: str = "USD"


quote = PriceQuote("AAPL", 18950)
assert quote == PriceQuote("AAPL", 18950, "USD")

try:
    quote.cents = 19000
except FrozenInstanceError:
    blocked = True
else:
    blocked = False

assert blocked
print(f"{quote.symbol} {quote.cents} {quote.currency}")
AAPL 18950 USD