I'm having trouble reinitializing nested dataclass object.
I have 2 nested dataclasses set up like so:
from dataclasses import dataclass, field
from typing import Dict
@dataclass
class MyNestedClass():
field1: str = ""
field2: int = 0
field3: Dict[str, float] = field(default_factory=dict)
@dataclass
class MyClass():
field1: str = ""
field2: int = 0
field3: Dict[str, float] = field(default_factory=dict)
field4: MyNestedClass = MyNestedClass()
As part of a unit testing procedure, I would like to initialize a new MyClass object and then run a test. However, I've noticed something odd. When I reinitialize my MyClass object, it somehow remembers the contents of field4. For example:
my_obj = MyClass()
print(my_obj)
my_obj.field2 = 1
my_obj.field3 = {'something': 2.5}
my_obj.field4.field1 = "B"
my_obj.field4.field2 = 2
my_obj.field4.field3 = {'something else': 3.14}
print(my_obj)
my_obj = MyClass()
print(my_obj)
yields
MyClass(field1='', field2=0, field3={}, field4=MyNestedClass(field1='', field2=0, field3={}))
MyClass(field1='', field2=1, field3={'something': 2.5}, field4=MyNestedClass(field1='B', field2=2, field3={'something else': 3.14}))
MyClass(field1='', field2=0, field3={}, field4=MyNestedClass(field1='B', field2=2, field3={'something else': 3.14}))
does the autogenerated dataclass constructor for MyClass not call the constructor for MyNestedClass by default? If not, what is it doing instead and what is the correct way to do this?
As Michael points out, the constructor generated by the
@dataclassdecorator includes a mutable default argument so that an instance ofMyNestedClassis created only once when theMyClassis defined and not uniquely for each instantiation.Defining
MyClassusing a field resolves this problem: