Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing a nested class from another nested dataclass

Now the following code works perfectly with Python 3.7

class A:
    class B:
        def __init__(self):
            print("B")

    class C:
        def __init__(self):
            self.b = A.B()

def main():
    a = A.C()

if __name__ == "__main__":
    main()

It prints a B on the screen.

However, with a small modification that tries to introduce dataclass, the code cannot run well.

from dataclasses import dataclass

class A:
    class B:
        def __init__(self):
            print("B")

    @dataclass
    class C:
        b = A.B()

def main():
    a = A.C()

if __name__ == "__main__":
    main()

Python reports -- for b = A.B() -- NameError: name 'A' is not defined.

Does anyone know how to fix this issue to achieve the same result with dataclass? And why does it say name 'A' is not defined?

like image 468
aafulei Avatar asked Mar 31 '26 05:03

aafulei


1 Answers

A class object is not created until the end of body of a class statement is reached, which is why your class A cannot be referenced while it is still being defined. Referencing A inside the __init__ method, on the other hand, is valid because the class A is already defined when the __init__ method is called.

You can instead use typing.TypeVar to define a forward-referencing type A.B for b, and assign to it a default value of a field with a default_factory function that returns an instance of A.B when called:

from dataclasses import dataclass, field
from typing import TypeVar

class A:
    class B:
        def __init__(self):
            print("B")

    @dataclass
    class C:
        b: TypeVar('A.B') = field(default_factory=lambda: A.B())

def main():
    a = A.C()

if __name__ == "__main__":
    main()

This outputs:

B
like image 98
blhsing Avatar answered Apr 02 '26 18:04

blhsing



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!