Why is a mutable dataclass default rejected, and what pattern should I use?
Quick answer
A list is mutable, so a direct list default can be shared by dataclass instances. Use field(default_factory=list) to have a fresh list created when a default is needed. Python 3.11 changed dataclasses to reject unhashable defaults as an approximation for mutability; the exact rejection behavior depends on Python version. [S1]
The question, the details, the next step.
A practical checklist
Identify fields with mutable defaults, such as lists, dictionaries, or sets.
Use
field(default_factory=...)when each instance needs a newly created value.Use a zero-argument callable that returns the desired default.
Do not specify both
defaultanddefault_factoryfor one field.Check that changing one instance’s collection leaves another instance’s collection unchanged.
Run relevant tests with the Python version used by your project.
A few more useful answers
Why might the same definition work on an older Python version?
Python 3.11 changed the check to reject unhashable defaults as an approximation for mutability. Older versions may allow a direct list default, even though sharing it between instances remains a risk. [S1]
Does the unhashable-default check detect every mutable value?
No. The documentation describes it as an approximation for mutability, not a universal test. Use a factory when each instance needs its own mutable value. [S1]
Can a factory create a collection with custom initial contents?
Yes. Use a zero-argument callable that returns the desired default value, such as a function that creates a dictionary with initial entries. [S1]
Sources
References used for this guide.
- [S1] Python dataclasses — field defaults and default_factory docs.python.org · Checked
