Python的global关键字如何工作?
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 个回答
在Python中,有本地上下文(默认的)和全局上下文。每当一个函数开始运行时,都会为它单独初始化一个新的本地上下文,这个上下文一开始是空的。而全局上下文就是全局的,几乎模块中的每个部分都可以共享它。
通过使用global指令,你可以从全局上下文中引入一个变量,这样就可以避免在本地上下文中查找这个变量(因为本地上下文是空的,如果不这样做就会出错)。
当Python第一次解析函数代码时,它看到import json
这行代码,就会认为json
是一个局部变量。(如果你给json
赋值,比如json = 'Hello World!'
,也会发生同样的事情。)当执行json.dumps
时,Python会在局部范围内查找json
,但找不到它(所以就会报错)。
在第二种情况下,当你加上global
时,Python在解析函数时会知道要在全局范围内查找json
。在你的例子中,json
已经被导入了,所以没问题。这样做还告诉Python,任何对json
的赋值(或导入)都应该在全局范围内存储这个名字(和相关的值),而不是在局部范围内。
在一个函数里给一个名字赋值,就会把这个名字变成这个函数的局部变量。无论你在函数的哪个地方赋值,就算是最后一行,这个名字都是局部的。如果你在赋值之前就用这个局部名字,就会出现你看到的错误。
即使这个名字在全局范围内也能用,这也没关系。编译器只会在局部范围内查找这个名字,因为它知道这个名字是局部的。
导入语句也是一种赋值方式。在函数里写的“import json”这句代码,会把“json”这个名字变成局部的。你在导入之前就使用了这个名字,所以你用的是一个未绑定的局部变量。
而“global”语句的意思是,尽管这个名字在赋值语句中被使用,但它不是局部的,而是全局的。在你的第二个函数中,global语句让“json”这个名字指向全局的“json”,而这个全局的“json”在你尝试访问它时已经被定义了,所以你的函数可以正常工作。