Python的global关键字如何工作?

0 投票
3 回答
529 浏览
提问于 2025-04-19 23:01
import json

def test():
    print json.dumps({'k': 'v'})
    import json

if __name__ == '__main__':
    test()

会抛出一个异常:

UnboundLocalError: local variable 'json' referenced before assignment

加上 global 关键字

import json

def test():
    global json
    print json.dumps({'k': 'v'})
    import json

if __name__ == '__main__':
    test()

这样就可以了。

3 个回答

-1

在Python中,有本地上下文(默认的)和全局上下文。每当一个函数开始运行时,都会为它单独初始化一个新的本地上下文,这个上下文一开始是空的。而全局上下文就是全局的,几乎模块中的每个部分都可以共享它。

通过使用global指令,你可以从全局上下文中引入一个变量,这样就可以避免在本地上下文中查找这个变量(因为本地上下文是空的,如果不这样做就会出错)。

1

当Python第一次解析函数代码时,它看到import json这行代码,就会认为json是一个局部变量。(如果你给json赋值,比如json = 'Hello World!',也会发生同样的事情。)当执行json.dumps时,Python会在局部范围内查找json,但找不到它(所以就会报错)。

在第二种情况下,当你加上global时,Python在解析函数时会知道要在全局范围内查找json。在你的例子中,json已经被导入了,所以没问题。这样做还告诉Python,任何对json的赋值(或导入)都应该在全局范围内存储这个名字(和相关的值),而不是在局部范围内。

2

在一个函数里给一个名字赋值,就会把这个名字变成这个函数的局部变量。无论你在函数的哪个地方赋值,就算是最后一行,这个名字都是局部的。如果你在赋值之前就用这个局部名字,就会出现你看到的错误。

即使这个名字在全局范围内也能用,这也没关系。编译器只会在局部范围内查找这个名字,因为它知道这个名字是局部的。

导入语句也是一种赋值方式。在函数里写的“import json”这句代码,会把“json”这个名字变成局部的。你在导入之前就使用了这个名字,所以你用的是一个未绑定的局部变量。

而“global”语句的意思是,尽管这个名字在赋值语句中被使用,但它不是局部的,而是全局的。在你的第二个函数中,global语句让“json”这个名字指向全局的“json”,而这个全局的“json”在你尝试访问它时已经被定义了,所以你的函数可以正常工作。

撰写回答