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