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

It looks like my question was quite clearly answered in the docs (which derived from PEP 557, as shmee mentioned):

Python stores default member variable values in class attributes. Consider this example, not using dataclasses:

class C:
    x = []
    def add(self, element):
        self.x.append(element)

o1 = C()
o2 = C()
o1.add(1)
o2.add(2)
assert o1.x == [1, 2]
assert o1.x is o2.x

Note that the two instances of class C share the same class variable x, as expected.

Using dataclasses, if this code was valid:

@dataclass
class D:
    x: List = []
    def add(self, element):
        self.x += element

it would generate code similar to:

class D:
    x = []
    def __init__(self, x=x):
        self.x = x
    def add(self, element):
        self.x += element

This has the same issue as the original example using class C. That is, two instances of class D that do not specify a value for x when creating a class instance will share the same copy of x. Because dataclasses just use normal Python class creation they also share this behavior. There is no general way for Data Classes to detect this condition. Instead, dataclasses will raise a ValueError if it detects a default parameter of type list, dict, or set. This is a partial solution, but it does protect against many common errors.

Leave a Comment