Frozen Dataclasses

Learn the concept of frozen dataclasses and their implementation in Python.

We'll cover the following


The general case for dataclasses is to create mutable objects. The state of an object can be changed by assigning new values to the attributes. This isn’t always a desirable feature, and we can make a dataclass immutable.

We can describe the UML diagram of the design by adding a stereotype of «Frozen». This notation can help to remind us of the implementation choice of making the object immutable. We must also respect an important rule of frozen dataclasses: an extension via inheritance must also be frozen.

The definition of the frozen Sample objects must be kept separate from the mutable objects that are part of processing an unknown or testing sample. This splits our design into two families of classes:

  • A small hierarchy of immutable classes, specifically Sample and KnownSample
  • Some associated classes that leverage these frozen classes


The related classes for testing samples, training samples, and unknown samples form a loose collection of classes with nearly identical methods and attributes. We can call this a “paddling” of related classes. This comes from the duck typing rule: “When I see a bird that walks like a duck and quacks like a duck, I call that bird a duck.” Objects created from classes with the same attributes and methods are interchangeable, even though they lack a common abstract superclass.

We can describe this revised design with a diagram like this:

Get hands-on with 1200+ tech skills courses.