您如何从类定义中的列表理解访问其他类变量?以下在 Python 2 中有效,但在 Python 3 中失败:
class Foo:
x = 5
y = [x for i in range(1)]
Python 3.2 给出错误:
NameError: global name 'x' is not defined
尝试 Foo.x
也不起作用。关于如何在 Python 3 中执行此操作的任何想法?
一个稍微复杂一点的激励示例:
from collections import namedtuple
class StateDatabase:
State = namedtuple('State', ['name', 'capital'])
db = [State(*args) for args in [
['Alabama', 'Montgomery'],
['Alaska', 'Juneau'],
# ...
]]
在此示例中, apply()
本来是一个不错的解决方法,但遗憾的是它已从 Python 3 中删除。
原文由 Mark Lodato 发布,翻译遵循 CC BY-SA 4.0 许可协议
类作用域和列表、集合或字典理解以及生成器表达式不会混合。
为什么;或者,关于这个的官方说法
在 Python 3 中,列表推导被赋予了它们自己的适当范围(局部命名空间),以防止它们的局部变量渗入周围的范围(请参阅 列表推导即使在推导范围之后也重新绑定名称。这是对的吗? )。在模块或函数中使用这样的列表理解时,这很棒,但在类中,作用域有点,嗯, _奇怪_。
这记录在 pep 227 中:
在
class
复合语句文档中:强调我的;执行框架是临时范围。
因为作用域被重新用作类对象的属性,允许它用作非本地作用域也会导致未定义的行为;例如,如果类方法引用
x
作为嵌套范围变量,然后操作Foo.x
会发生什么?更重要的是,这对于Foo
的子类意味着什么? Python 必须 以不同的方式对待类范围,因为它与函数范围非常不同。最后但同样重要的是,执行模型文档中链接的 命名和绑定 部分明确提到了类作用域:
y = [x for i in range(1)]
^^^^^^^^
# Runs fine y = [i for i in range(x)]
# NameError y = [i for i in range(1) for j in range(x)]
^^^^^^^^^^^^^^^^^ —————–
outer loop inner, nested loop
5 19 LOAD_FAST 0 (Foo) 22 RETURN_VALUE
3 16 LOAD_CONST 1 (5) 19 STORE_NAME 3 (x)
4 22 LOAD_CONST 2 (
at 0x10a385420, file “”, line 4>)
25 LOAD_CONST 3 (‘foo..Foo.’)
28 MAKE_FUNCTION 0
31 LOAD_NAME 4 (range)
34 LOAD_CONST 4 (1)
37 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
40 GET_ITER
41 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
44 STORE_NAME 5 (y)
47 LOAD_CONST 5 (None)
50 RETURN_VALUE
2 0 LOAD_NAME 0 (name) 3 STORE_NAME 1 (module)
3 6 LOAD_CONST 0 (5) 9 STORE_NAME 2 (x)
4 12 BUILD_LIST 0 15 LOAD_NAME 3 (range) 18 LOAD_CONST 1 (1) 21 CALL_FUNCTION 1 24 GET_ITER >> 25 FOR_ITER 12 (to 40) 28 STORE_NAME 4 (i) 31 LOAD_NAME 2 (x) 34 LIST_APPEND 2 37 JUMP_ABSOLUTE 25 >> 40 STORE_NAME 5 (y) 43 LOAD_LOCALS 44 RETURN_VALUE
def init(self): self.y = [self.x for i in range(1)]
from collections import namedtuple State = namedtuple(‘State’, [‘name’, ‘capital’])
class StateDatabase: db = [State(*args) for args in [ (‘Alabama’, ‘Montgomery’), (‘Alaska’, ‘Juneau’), # … ]]
”`