查詢名稱時,函式會跳過類範圍

類在定義期間具有區域性作用域,但在查詢名稱時,類中的函式不使用該作用域。因為 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

不熟悉此範圍如何工作的使用者可能希望 bce 列印 class

PEP 227

無法訪問類範圍中的名稱。名稱在最裡面的封閉函式範圍內解析。如果類定義出現在巢狀作用域鏈中,則解析過程將跳過類定義。

從 Python 的命名和繫結文件 :

類塊中定義的名稱範圍僅限於類塊; 它沒有擴充套件到方法的程式碼塊 - 這包括瞭解和生成器表示式,因為它們是使用函式作用域實現的。這意味著以下內容將失敗:

class A:
    a = 42
    b = list(a + i for i in `range(10)`)

此示例使用 Martijn Pieters 的回答中的參考文獻,其中包含對此行為的更深入分析。