您面临的问题是因为您不了解类声明的作用域是如何工作的。类声明在其自己的作用域内执行。执行完成后,将创建一个新的类对象,并将获得的范围作为其__dict__附加到该类。在
注意:类范围是从方法范围内搜索的而不是!这意味着当在方法定义中时,必须将类属性引用为MyClass.attribute。在
例如:class MyClass:
var = 1
# we are executing this code as a single block
# so you must reference the variable as is usual
print(var)
# default values are *not* inside the definition.
# they are evaluated in the outer scope, so use plain "var" here
def method(self, a_default=var):
print(a_default)
def other_method(self):
# inside methods you are in a different scope
print(MyClass.var)
# equivalent *if* no "var" instance attributes exists
print(self.var)
注意:由于该类在执行其声明时仍然不存在,因此无法在MyClass声明的“顶层”引用MyClass:
^{pr2}$
其副作用是以下代码:class MyClass:
x = 1
results = list(i+x for i in range(10))
产生:NameError Traceback (most recent call last)
in ()
> 1 class MyClass:
2 x = 1
3 results = list(i+x for i in range(10))
4
in MyClass()
1 class MyClass:
2 x = 1
> 3 results = list(i+x for i in range(10))
4
in (.0)
1 class MyClass:
2 x = 1
> 3 results = list(i+x for i in range(10))
4
NameError: name 'x' is not defined
因为生成器表达式(以及python3中的列表理解)实际上被认为是具有自己作用域的函数。由于没有从内部函数作用域搜索类范围,因此找不到x。在
您可以使用函数定义和默认值来解决此问题:class MyClass:
x = 1
def _make_results(x=x):
return list(i+x for i in range(10))
results = _make_results()
del _make_results # otherwise it would be added as a method.
# or:
results = (lambda x=x: list(i+x for i in range(10)))()
这通常不是问题,因为类定义很少包含方法定义和一些常量之外的任何内容。在
关于类作用域,已经有一些问题: