๐Ÿ Python dataclasses: the list that wanted roommates

You create two objects. You update the list in one. Somehow, the other object knows about it.

Congratulations: your objects are sharing. Unfortunately, nobody asked them to.

๐Ÿง  The tiny trap

Python’s ordinary class attributes can be shared between instances. Dataclasses protect against many mutable-default mistakes by rejecting unhashable defaults, including a plain list, in current Python versions.

So this raises a ValueError:

from dataclasses import dataclass

@dataclass
class Task:
    tags: list[str] = []

๐Ÿ”ง The fix

Let each instance create its own list:

from dataclasses import dataclass, field

@dataclass
class Task:
    tags: list[str] = field(default_factory=list)

default_factory calls the supplied zero-argument function when a default is needed. Here, list creates a fresh list for each instance.

๐Ÿ’ญ My take

If a dataclass owns a list or dictionary, default_factory is my default reflex. Pun mildly intended.

It’s explicit, readable, and saves the next developer from wondering why Task A knows Task B’s secrets.

One nuance: this is about creating a fresh container. It doesn’t magically deep-copy objects you later put inside that container.

Tiny rule, fewer weird bugs. I’ll take it. โœจ

๐Ÿ“š The receipts: Python dataclasses documentation ยท Class and instance variables