python3在初始化时访问生成器中的类属性

标签 python python-3.x class namespaces

<分区>

我目前正在将 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]

关于发生了什么的任何指示?

最佳答案

关于第一种情况,您所拥有的实际上是将生成器表达式传递给甚至不是类属性的 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 和 3.X 中引发了 NameError。原因是函数有自己的命名空间,并且没有特别声明该变量的状态(全局、局部、非局部)或通过类的实例访问 (self.var1) 函数不会可以访问外部有界命名空间。

另一方面,列表推导式在 python-2 中可以访问定义它们的对象的命名空间。它们不像函数,没有函数所具有的许多特性。这实际上是一种双向关系。这就是说,虽然您可以在列表推导内使用变量,但您在列表推导内定义的内容也可以在其外部访问。并且由于人们倾向于在列表理解中使用一次性变量,这将导致您的代码出现变量泄漏。但是由于 Python-3.x 列表理解从函数中借用了私有(private)命名空间,因此它们可以拥有自己的命名空间。

关于python3在初始化时访问生成器中的类属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50229813/

相关文章:

c++ - 如何删除对象之间的变量共享?

python - cython:字符串 ndarray 的内存 View (或直接 ndarray 索引)

python - z3变量类型切换

c# - 具有相同名称的非通用类和通用类的不良做法?

python - 多个 numpy 数组的矩阵乘法

python - print 的 end 参数会导致 time.sleep 的不同行为

Java.lang.classnotfoundException - HelloWorld.class

python - 在 python 中将初始化的字典打印为空

python - 禁用 QWizardPage 的下一个按钮上的默认焦点,并让自定义 QPushButton 由 'enter' 触发

python - 如何使用 python Psycopg2 和参数绑定(bind)在 postgres 数组列中插入?