Python类中的列表理解作用域规则是什么?

2024-06-25 23:18:28 发布

您现在位置:Python中文网/ 问答频道 /正文

{cd2>在下面的代码中工作。在

cc赋值在一个类中使用相同的列表理解,在Python2中工作,但在Python3中失败。在

是什么解释了这种行为?在

ml1 = "a b c".split()
ml2 = "1 2 3".split()
mc = [ i1 + i2 for i1 in ml1 for i2 in ml2 ]

class Foo(object):
    cl1 = ml1
    cl2 = ml2

    cc1 = [ i1 for i1 in cl1 ]
    cc2 = [ i2 for i2 in cl2 ]
    cc = [ i1 + i2 for i1 in cl1 for i2 in cl2 ]


print("mc = ", mc)
foo = Foo()
print("cc = ", foo.cc)

我明白了:

^{pr2}$

为什么没有定义类变量cl2?注意,cc2赋值工作正常,cc1也一样。在理解中交换cl1和{}表明第二个循环是触发异常的循环,而不是{}本身。)

版本:

(default-3.5) snafu$ python2 --version
Python 2.7.11+
(default-3.5) snafu$ python3 --version
Python 3.5.1+

Tags: inforfoomcccsplit赋值ml2
1条回答
网友
1楼 · 发布于 2024-06-25 23:18:28

Python规则的作用域与它们自己的作用域相同。你知道一个类的方法是如何不自动在类范围内查找变量的吗?在

class Example:
    var = 1
    def this_fails(self):
        print(var)
Example().this_fails()  # NameError

这同样适用于类作用域内嵌套的任何函数作用域,包括list comprehension的作用域。在列表理解中对cl2的查找绕过了类作用域,直接转到全局变量。它实际上是这样工作的:

^{pr2}$

注意,cl1查找工作正常,因为这发生在类范围内,在理解之外,尽管语法上嵌套在理解中。They made that decision当Python引入genexps时,因为它捕捉到了一些常见的genexp错误。这也是cc1cc2列表理解工作的原因;它们对类级别变量的唯一使用是在它们的外部(仅)foriterable中。在

在类语句中使用理解和生成器表达式是一团糟。不应该,但确实如此。坚持使用常规循环,或者在类语句之外运行理解,这样语义就更明显了。在

相关问题 更多 >