首页 > 解决方案 > 来自dict理解的Python类变量引用子类

问题描述

考虑这段代码

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

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

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

标签: pythonclassscopedictionary-comprehension

解决方案


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

为了避免绑定问题,定义一个B作为参数的函数,并让该函数执行 dict 理解:

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

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

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


推荐阅读