考虑这段代码
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/