首页 > 解决方案 > 如何引用嵌套的 Python 数据类?

问题描述

类似问答的注意事项:


我正在尝试@dataclass在另一个类中简单地嵌套多个 Python 装饰类,并让后面的类引用早期的类。如果我根本不嵌套它们,它们会按预期工作,能够将定义的第一个类包含到第二个类的对象中:

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}')

但是如果我尝试在另一个类(在这种情况下,不是数据类)中做同样的事情,“B”类就看不到“A”类。在下面的代码中,a作为类型的定义A失败并出现 NameError:“名称A未定义”。我试过A和CA,都不行。

请注意,C 类中的其他函数可以同时看到 A 和 B,只是在数据类 B 中看不到数据类 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()

但是,如果我将这些转换为普通的 Python 类,它可以在嵌套情况下工作:

重新检查,事实证明这在普通课程中也被破坏了(根据下面的评论)。

奇怪的是,如果将数据类 A 嵌套数据类 B 中,而 B 仍在类 C 中,它确实有效 - B 可以直接访问 A,但 C 类中的其他任何内容都不能直接访问 A。

问题

是否可以定义嵌套数据类,让后面的数据类在同一级别访问早期的数据类?如果是这样,怎么做?

标签: pythonpython-3.xclasspython-dataclasses

解决方案


据我所知,这是由于类定义的语义——强调我的:

然后使用新创建的本地命名空间和原始的全局命名空间在新的执行框架中执行该类的套件。(通常,套件主要包含函数定义。)当类的套件完成执行时,它的执行帧被丢弃,但它的本地命名空间被保存。

也就是说,任何类定义都只有模块全局命名空间(在这种情况下还不包含C,因为它的套件尚未完成执行)和一个新的空本地命名空间。

编辑

基于上述,这可以一起破解,但我真的不会这样做......

from dataclasses import dataclass, field


class C:
    @dataclass
    class A:
        z: int = field(default=0)

    globals()["A"] = A  # "and the original global namespace..."

    @dataclass
    class B:
        a: A = field(default=A(z=1))

    def __init__(self):
        self.b = C.B(a=C.A(z=3))

    def print_info(self):
        print(f"{self.b.a.z=}")


c = C()
c.print_info()

推荐阅读