Python
dataclasses
mutable defaults
class attributes
programming concepts

Why can't dataclasses have mutable defaults in their class attributes declaration?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Dataclasses reject mutable defaults such as empty lists or dictionaries because those objects would otherwise be shared by every instance. The restriction exists to prevent a very common Python bug where changing one instance silently changes the default state seen by another.

Why Mutable Defaults Are Dangerous

Class-level default expressions are evaluated once when the class is defined, not every time a new instance is created. If that default is mutable, all instances end up pointing at the same object.

A plain Python class can fall into this trap:

python
1class BadConfig:
2    def __init__(self, items=[]):
3        self.items = items
4
5a = BadConfig()
6b = BadConfig()
7
8a.items.append("x")
9print(b.items)  # ['x']

That shared list is usually not what the programmer wanted. Dataclasses detect the same pattern and stop you before the bug becomes part of your model.

What Dataclasses Want Instead

If each instance needs its own fresh list, use field(default_factory=...). The factory is called each time a new object is created, so every instance gets an independent value.

python
1from dataclasses import dataclass, field
2
3@dataclass
4class GoodConfig:
5    items: list[str] = field(default_factory=list)
6
7a = GoodConfig()
8b = GoodConfig()
9
10a.items.append("x")
11print(a.items)  # ['x']
12print(b.items)  # []

This is the correct dataclass pattern for lists, dictionaries, sets, and other mutable containers.

Why Dataclasses Raise an Error

The dataclass module is opinionated here on purpose. Instead of silently accepting a risky default, it raises an error and pushes you toward default_factory.

That design choice is useful because mutable-default bugs are hard to spot. The code may seem to work for a while, then later two objects unexpectedly share state. By failing early, dataclasses turn a subtle runtime bug into a clear definition-time correction.

Immutable Defaults Are Fine

Immutable values such as strings, integers, booleans, and tuples are safe as direct defaults because they cannot be modified in place.

python
1from dataclasses import dataclass
2
3@dataclass
4class JobSettings:
5    retries: int = 3
6    mode: str = "safe"
7    flags: tuple[str, ...] = ("fast-start",)

These defaults are not shared in the problematic sense because no instance can mutate them and affect the others.

That is why dataclasses are not banning all defaults. They are only guarding against the defaults that can leak shared state. It is a preventive rule, not a limitation without purpose. It prevents confusing shared-state bugs.

A Useful Mental Model

Think of default= as "reuse this value" and default_factory= as "create a new value each time." That is why default_factory=list is correct for containers and default=3 is correct for numbers.

Once that distinction is clear, the dataclass rule stops feeling arbitrary. It is simply protecting instance state from accidental sharing.

The same reasoning applies to dictionaries, sets, and custom mutable objects, not just to lists.

Common Pitfalls

  • 'items: list = [] is exactly the pattern dataclasses are trying to prevent.'
  • 'default_factory must receive a callable such as list, not the result of calling it.'
  • Tuples are immutable and safe as direct defaults, but lists and dictionaries are not.
  • The same mutable-default problem exists outside dataclasses too, especially in function arguments.

Summary

  • Dataclasses reject mutable defaults because they would be shared across instances.
  • Shared mutable state creates bugs that are subtle and hard to trace.
  • Use field(default_factory=list) or a similar factory for per-instance containers.
  • Direct defaults are fine for immutable values such as numbers, strings, and tuples.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.