Notes On Similar Q&As:
- This question is not addressed in Nested Python class needs to access variable in enclosing class, which is dealing with relationships between a "parent" and nested "child" class, and does not address
@dataclasses.dataclass
classes. - This question is not addressed in Python - reference inner class from other inner class. I though the code from the accepted answer there was working, but a double-check after a comment below shows it is not, when using normal classes.
I'm trying to do a simple nesting of multiple Python @dataclass
decorated classes within another class, and have later classes refer back to the earlier ones. If I do not nest them at all, they work as expected, being able to include the first class defined into an object in the second class:
from dataclasses import dataclass, field
@dataclass
class A:
z:int = field(default=0)
@dataclass
class B:
a:A = field(default=A(z=1)) ### Object that is class A is included in class B
b = B(a=A(z=3))
print(f'b = B(a=A(z=3)); b.a.z={b.a.z}; b={b}')
But if I try to do the same inside of another class (in this case, not a dataclass), the "B" class cannot see the "A" class. In the below code, the definition of a
as a type of A
fails with a NameError: "name A
is not defined". I've tried A and C.A, neither work.
Note that the other functions in the C class are able to see both A and B just fine, just inside dataclass B cannot see dataclass A.
class C:
@dataclass
class A:
z:int = field(default=0)
@dataclass
class B:
a:A = field(default=A(z=1)) ### NameError: name 'A' is not defined
def __init__(self):
self.b = C.B(a=C.A(z=3))
def print_info(self):
print(f'b = C.B(a=C.A(z=3)); b.a.z={self.b.a.z}; b={b}')
c = C()
c.print_info()
However, if I convert these to normal Python classes, it works in the nested case:
Rechecking, it turns out this is broken in normal classes as well (per comment below).
Strangely, if one nests dataclass A inside dataclass B, with B still inside class C, it does work - B has direct access to A, but nothing else in class C has direct access to A.
Question
Is it possible to define nested dataclasses with having the later ones access the earlier ones at the same level? If so, how?
CodePudding user response:
To my best understanding, this is due to the semantics for class definitions – emphasis mine:
The class’s suite is then executed in a new execution frame, using a newly created local namespace and the original global namespace. (Usually, the suite contains mostly function definitions.) When the class’s suite finishes execution, its execution frame is discarded but its local namespace is saved.
That is, any class definition only ever has the module-global namespace (which does not yet contain C
in this case, since its suite hasn't finished executing) and a new empty local namespace.