查找名称时,函数会跳过类范围

类在定义期间具有局部作用域,但在查找名称时,类中的函数不使用该作用域。因为 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 的回答中的参考文献,其中包含对此行为的更深入分析。