I have instances of a dataclass that reference each other.
from dataclasses import dataclass
@dataclass()
class Foo:
id: int
neighbor: 'Foo'
foo = Foo(1, None)
bar = Foo(2, foo)
foo.neighbor = bar
I really want a frozen class, since these objects must not be manipulated in a multi threaded run. But if I declare frozen=True
, the last line will obviously raise an error. I cannot think of a way how to deal with this. I read this thread but the solution does not work for me, since foo.neighbor
should point at another frozen instance.
Is there any way to achieve this? I am not bound to dataclasses. But I encounter the same problem using namedtuples.
frozen
works by overriding __setattr__
. You can by pass __setattr__
altogether by accessing your instance's __dict__
attribute directly.
foo.__dict__['neighbor'] = bar
I don't know if this will have any unintended side effects in general (and certainly won't work if you use __slots__
to prevent __dict__
from being created), but it might be sufficient for your use case.
(This may also fail in future versions of dataclass
, if the implementation changes to use a C extension rather than the current approach of dynamically generating source code to pass to exec
. namedtuple
evolved along those lines, I believe.)
Or, you can use the same trick that dataclasses
itself uses to initialize the attributes of a frozen class: use object.__setattr__
explicitly.
object.__setattr__(foo, 'neighbor', bar)