Python中自由变量的搜索顺序是什么?
具体来说,类的方法中的自由变量是如何在定义时绑定的呢?大概可以这样理解:
- 在外部函数的临时作用域中,会生成一个闭包。
- 在全局的永久作用域中,不会生成闭包(方法体执行时直接查找)。
- 如果找不到变量,就会抛出一个UnboundLocalError错误。
这里有两个例子:
globalname = 0
class Test(object):
def method(self):
print globalname
print Test
def outer():
localname = 1
class Test(object):
def method(self):
print globalname
print localname
print Test
return Test
Test().method.__func__.__closure__
# None
outer()().method.__func__.__closure__
# (<cell at 0xb7d655b4: type object at 0x82412bc>, <cell at 0xb7d655cc: int object at 0x81b20b0>)
我找不到太多关于它们在定义时是如何处理的文档。上面的解释正确吗?
1 个回答
2
在Python中,如果你在当前代码块里给一个变量赋值,Python就会认为这个变量是局部的。所以
spam = 0
def ham:
print( spam )
这段代码会让变量spam变成全局变量,但
spam = 0
def ham:
spam = 0
print( spam )
这段代码会创建一个新的变量,它只在ham
这个函数内部有效。闭包会抓取所有在外层作用域中的局部变量。在你的第一个例子中,没有局部变量,所以没有闭包;而在第二个例子中,localname
被赋值了,因此method
就是一个闭包。
在Python中,总是有办法绕过这个假设。global
关键字可以声明一个变量为全局变量(!),所以例如
spam = 0
def ham:
global spam
spam = 0
print( spam )
这段代码将不会是一个闭包。Python 3引入了nonlocal
关键字,它告诉Python向上查找作用域,直到找到变量名并引用它。