来自 dict 理解引用子类的 Python 类变量

标签 python class scope dictionary-comprehension

考虑这段代码

class A:
    class B:
        foo = 1
    bar = {x: B for x in range(5)}

这将产生一个错误,指出 B 未定义。但是,当调试器在相应行停止时,在 REPL 上,我可以很好地运行该代码。这似乎是一些嵌套/范围问题,但我不明白。

有人可以解释发生了什么,以及如何解决这个问题吗?

最佳答案

字典理解隐含地定义了一个匿名函数。在该函数体内,B 是一个自由变量。变量查找规则声明 B 的值取自定义 B 的最近封闭范围,但是 语句没有定义作用域(尽管它确实定义了一个类似于适当作用域的临时命名空间)。匿名函数的局部作用域的下一个作用域是全局作用域,其中未定义 B

为了避免绑定(bind)问题,定义一个以 B 作为参数的函数,并让该函数执行字典理解:

bar = (lambda cls: {x: cls for x in range(5)})(B)

现在,B 可以在 class 语句的当前命名空间中找到(避免了作用域规则),并且 cls 是在 lambda 表达式定义的匿名函数的范围内定义,现在可以在 dict 理解使用的范围堆栈中找到。换句话说,理解创建的匿名函数是对 lambda 表达式函数范围的闭包。

也就是说,嵌套类在 Python 中并不常见;您可以在全局范围内定义 B 来解决这种情况下的问题。

关于来自 dict 理解引用子类的 Python 类变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58559184/

相关文章:

Objective-C - iVar 作用域方法变量?

python - 如何让 Sublime 2 与 Python 2.7 一起工作

Python Pandas - 通过将标签与列匹配来将一个数据框的值添加到另一个数据框中

python - 使用 numpy 从图像数组的 RGB 值获取 (x,y) 坐标值

c++ - 不能将变量声明为类型,因为以下虚函数是抽象的

c++ - 用于授予对类数据成员的访问权限的选项 (C++)

javascript - .apply 不改变范围

python - Keras 无法加载数据集或应用程序

C++ 类迭代器实用程序 : definition and usage

c# - OOP 接口(interface)和基类