我目前正在将codebase
从python2切换到python3并遇到一个我不太明白的问题:
class MyClass:
var1 = True
var2 = tuple([i for i in [1, 2,] if var1])
上面的类在python2中运行得很开心,但是在python3中运行了。
我把它改为:
class MyClass:
var1 = True
var2 = tuple(i for i in [1, 2,] if var1)
因为我的理解是列表理解是多余的,无论它不起作用。经过一些调查后,似乎list/tuple
理解的行为方式我不太明白,当他们在一个正在初始化的班级中时。
# Breaks in python 2 and 3
class MyClass:
var1 = True
var2 = tuple(i for i in [1, 2,] if var1)
# Works in python 2, breaks in 3
class MyClass:
var1 = True
var2 = [i for i in [1, 2,] if var1]
关于进展情况的任何指示?
答案 0 :(得分:1)
关于第一种情况,你所拥有的实际上是将生成器表达式传递给tuple
函数,该函数甚至不是类属性。它实际上类似于以下代码:
>>> class MyClass:
... var1 = True
... def func():
... return var1
... func()
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in MyClass
File "<stdin>", line 4, in func
NameError: global name 'var1' is not defined
你可以看到再次在Python-2.7中引发NameError
并且肯定是3.X.原因是函数有自己的命名空间,没有特别声明该变量的状态(全局,本地,非本地)或通过类的实例(self.var1
)访问,但是函数无法访问外部有界-namespaces。
另一方面,列表推导在python-2中可以访问定义它们的对象的命名空间。它们不像函数,并且没有许多功能。这实际上是一种双面关系。这就是说,虽然您可以在列表内容中使用变量,但您在list compurehenion中定义的内容也可以在其外部访问。而且因为人们倾向于在列表推导中使用一次性变量,这将导致代码具有可变泄漏。但是,由于Python-3.x列表解析从函数中借用了私有名称空间,因此它们可以拥有自己的命名空间。