如何从类定义中的列表理解中访问其他类变量?以下代码在python2中有效,但在python3中无效:
class Foo:
x = 5
y = [x for i in range(1)]
Python 3.2给出了以下错误:
NameError: global name 'x' is not defined
尝试Foo。X也不行。关于如何在python3中做到这一点,有什么想法吗?
一个稍微复杂一点的激励例子:
from collections import namedtuple
class StateDatabase:
State = namedtuple('State', ['name', 'capital'])
db = [State(*args) for args in [
['Alabama', 'Montgomery'],
['Alaska', 'Juneau'],
# ...
]]
在这个例子中,apply()本来是一个不错的解决方案,但不幸的是,它从Python 3中被删除了。
由于最外层的迭代器是在周围范围内计算的,我们可以将zip与itertools一起使用。重复将依赖项转移到理解范围:
import itertools as it
class Foo:
x = 5
y = [j for i, j in zip(range(3), it.repeat(x))]
还可以在推导式中使用嵌套for循环,并在最外层的可迭代对象中包含依赖项:
class Foo:
x = 5
y = [j for j in (x,) for i in range(3)]
对于OP的具体例子:
from collections import namedtuple
import itertools as it
class StateDatabase:
State = namedtuple('State', ['name', 'capital'])
db = [State(*args) for State, args in zip(it.repeat(State), [
['Alabama', 'Montgomery'],
['Alaska', 'Juneau'],
# ...
])]
在我看来,这是Python 3的一个缺陷。我希望他们能改变。
旧方法(适用于2.7,抛出NameError: name 'x'未在3+中定义):
class A:
x = 4
y = [x+i for i in range(1)]
注意:简单地用A.x限定它的作用域并不能解决这个问题
新方法(适用于3岁以上):
class A:
x = 4
y = (lambda x=x: [x+i for i in range(1)])()
因为语法太丑了,我通常只在构造函数中初始化所有的类变量