查詢名稱時,函式會跳過類範圍
類在定義期間具有區域性作用域,但在查詢名稱時,類中的函式不使用該作用域。因為 lambdas 是函式,並且使用函式作用域來實現理解,所以這可能導致一些令人驚訝的行為。
a = 'global'
class Fred:
a = 'class' # class scope
b = (a for i in range(10)) # function scope
c = [a for i in range(10)] # function scope
d = a # class scope
e = lambda: a # function scope
f = lambda a=a: a # default argument uses class scope
@staticmethod # or @classmethod, or regular instance method
def g(): # function scope
return a
print(Fred.a) # class
print(next(Fred.b)) # global
print(Fred.c[0]) # class in Python 2, global in Python 3
print(Fred.d) # class
print(Fred.e()) # global
print(Fred.f()) # class
print(Fred.g()) # global
不熟悉此範圍如何工作的使用者可能希望 b
,c
和 e
列印 class
。
從 PEP 227 :
無法訪問類範圍中的名稱。名稱在最裡面的封閉函式範圍內解析。如果類定義出現在巢狀作用域鏈中,則解析過程將跳過類定義。
從 Python 的命名和繫結文件 :
類塊中定義的名稱範圍僅限於類塊; 它沒有擴充套件到方法的程式碼塊 - 這包括瞭解和生成器表示式,因為它們是使用函式作用域實現的。這意味著以下內容將失敗:
class A: a = 42 b = list(a + i for i in `range(10)`)
此示例使用 Martijn Pieters 的回答中的參考文獻,其中包含對此行為的更深入分析。