Python中自由变量的搜索顺序是什么?

0 投票
1 回答
568 浏览
提问于 2025-04-16 02:05

具体来说,类的方法中的自由变量是如何在定义时绑定的呢?大概可以这样理解:

  1. 在外部函数的临时作用域中,会生成一个闭包。
  2. 在全局的永久作用域中,不会生成闭包(方法体执行时直接查找)。
  3. 如果找不到变量,就会抛出一个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向上查找作用域,直到找到变量名并引用它。

撰写回答