Use default factory to initialize nested dataclass fields

A quick take on how to avoid problems with nested dataclasses

I you happen to work with nested Python dataclasses , then maybe you’ve noticed an issues with defining field values by creating an instance of some object.

In the example below, all instances of class Main will point to the same instance of class Sub:

from dataclasses import dataclass, field

@dataclass
class Sub:
    prop: str = field(default="some value")

@dataclass
class Main:
    sub: Sub = Sub()


m1 = Main()
m2 = Main()

id(m1)
Out[1]: 140304747921264

id(m2)
Out[2]: 140304748528400

assert id(m1.sub) != id(m2.sub)
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-8-63c2e0b3d3f5> in <module>
----> 1 assert id(m1.sub) != id(m2.sub)

AssertionError:

The fix is really easy. Simply provide the name of the class you want to instantiate as default_factory argument to the field function:

from dataclasses import dataclass, field

@dataclass
class Sub:
    prop1: str = field(default="some value")

@dataclass
class Main:
    sub: Sub = field(default_factory=Sub)

m1 = Main()
m2 = Main()

assert id(m1.sub) != id(m2.sub)

This way you’ll correctly initialize field values.