Prevent a mutable default list in a dataclass

dataclasses.field(default_factory=list) calls list separately whenever an instance needs its default. That gives each TodoList an independent empty list. In the example, morning receives one item while evening remains empty; the identity assertion checks that the two attributes are not the same list object.

This matters for per-instance state such as pending tasks, warnings, or collected results. A shared mutable default would let one instance’s mutation become visible through another instance. Current dataclasses reject ordinary unhashable defaults as a guard against this common mistake, but default_factory is the direct, readable way to express the intended ownership.

The factory must be a zero-argument callable. list is appropriate here because it constructs an empty list each time; use another suitable factory when the desired initial value differs. This only separates defaults created by the dataclass. Passing the *same* list explicitly to two constructors would still intentionally share it. Dataclasses were added in Python 3.7. See the official field() documentation.

AI assistance disclosure: this article was drafted with AI assistance and should be adapted to the application’s own data rules.

from dataclasses import dataclass, field


@dataclass
class TodoList:
    items: list[str] = field(default_factory=list)


morning = TodoList()
evening = TodoList()
morning.items.append("write tests")

assert morning.items == ["write tests"]
assert evening.items == []
assert morning.items is not evening.items

print(morning.items)
print(evening.items)
['write tests']
[]

Comments

Popular posts from this blog

Compare Two Text Files in Python Without Modifying Them

Seven CSV Quality Checks to Run Before Importing Data

Explain why SQLite transactions cannot make an HTTP call atomic