您面臨的問題是因為您不了解類聲明的作用域是如何工作的。類聲明在其自己的作用域內執行。執行完成后,將創建一個新的類對象,并將獲得的范圍作為其__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)))()
這通常不是問題,因為類定義很少包含方法定義和一些常量之外的任何內容。在
關于類作用域,已經有一些問題: