frozen=True and slots=True solve different problems in Python dataclasses: freezing guards against ordinary field reassignment, while slots constrain instance attributes and can remove the usual per-instance dictionary. Use either—or both—when its trade-offs fit your model; neither makes objects universally immutable or guarantees a performance improvement.
What frozen dataclasses and slots each change
| Choice | What it does | What it does not do |
|---|---|---|
frozen=True |
Adds guards against assigning to or deleting instance fields after initialization. Such attempts raise FrozenInstanceError. |
It does not make referenced objects deeply immutable or prevent every possible mutation in Python. |
slots=True |
Generates __slots__ and constrains instance attributes; absent an instance dictionary supplied by a base class or explicitly included, instances do not have the usual automatic __dict__. |
It does not protect existing field values from mutation or guarantee a particular memory or speed improvement. |
The Python documentation states, “It is not possible to create truly immutable Python objects.” That is why “frozen” is best understood as a practical assignment guard, not a promise of absolute immutability. Python dataclasses documentation.
As an Amazon Associate I earn from qualifying purchases.
When to use frozen dataclasses
Choose frozen=True when a model should behave like a value whose fields are not ordinarily reassigned after construction. It can make accidental updates fail visibly and, with the default equality setting, affects whether dataclasses generate a hash.
Freezing only guards the field binding. For example, if a frozen object holds a list, code cannot normally replace the list field, but can still mutate the list’s contents. For value semantics, use immutable field types where appropriate or deliberately normalize inputs into immutable representations.
#1 Best Overall
There is also a construction cost: the Python dataclasses documentation describes a “tiny performance penalty” because generated initialization cannot use simple assignment and must use __setattr__(). The documentation gives no numeric benchmark, so the practical impact should be evaluated in the application’s own workload rather than assumed.
When to use slots
Slots are useful when the set of attributes should be constrained or when an application creates enough instances that reducing per-instance overhead may matter. Their effect depends on the class hierarchy and workload; do not assume a universal memory saving or speedup.
Rank #2
- Use slots when a fixed attribute set is a useful design constraint.
- Measure memory and runtime in the actual application before adopting slots solely for optimization.
- Check base classes: inheriting from a class without slots can restore an instance dictionary and weak-reference support.
- Check weak-reference requirements. Slotted objects need a
__weakref__slot for weak references; dataclasses provideweakref_slot=Truefor this purpose, used withslots=True.
These mechanics and inheritance behavior are described in the Python data model documentation.
Combining the options
A small coordinate value can use both options when its fields should not be rebound and its attribute set should remain fixed:
from dataclasses import dataclass
@dataclass(frozen=True, slots=True)
class Point:
x: float
y: float
point = Point(1.0, 2.0)
point.x = 3.0 # raises FrozenInstanceError
The two options remain independent: remove frozen=True if fields should be assignable, or remove slots=True if instances need a normal dynamic attribute dictionary. Combining them does not make mutable objects referenced by fields immutable.
Version and inheritance details to check
- Dataclass
slotssupport was added in Python 3.10. Code targeting earlier versions cannot rely on this decorator option. - Python 3.11 changed inherited-slot handling so generated slots do not duplicate names already present in base classes. Use
dataclasses.fields()to enumerate dataclass fields; do not treat__slots__as the field list. slots=Truereturns a new class, which is a relevant compatibility detail for code that relies on class identity or decorator behavior.- Review the target Python version’s dataclass and data model documentation when supporting a range of interpreters, especially where inheritance and weak references are involved.
Hashing and equality are a separate design decision
With the default eq=True, combining it with frozen=True causes dataclasses to generate a hash. That is not a reason by itself to make a class frozen: hashability is useful only when equality and the values participating in the hash match the intended value semantics. Consider whether those field values can themselves change before relying on an instance as a dictionary key or set member. The dataclasses documentation describes the generated hash rules.
A practical choice checklist
- Need ordinary field reassignment to fail? Consider
frozen=True. - Need dynamic per-instance attributes? Avoid slots, or ensure a base class supplies the required dictionary.
- Need weak references to instances? Account for
__weakref__support, usingweakref_slot=Truewith dataclass slots where appropriate. - Need memory or runtime optimization? Benchmark representative application workloads and account for inherited classes.
- Need compatibility with Python before 3.10? Do not use dataclass
slots=True. - Need dataclass field names? Use
dataclasses.fields(), not__slots__.
Further reading
For a broader treatment of Python data classes and memory-conscious object design, O’Reilly lists both subjects in Fluent Python, 2nd Edition by Luciano Ramalho, published in April 2022 (ISBN 9781492056348). Publisher page.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Quick Recap
Best Value
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




