两个关键词都用于允许在一个局部作用域中使用外层的变量。
- global 表示将变量声明为全局变量
- nonlocal 表示将变量声明为外层变量(外层函数的局部变量,而且不能是全局变量)
- python引用变量的顺序如下:
- 当前作用域局部变量
- 外层作用域变量
- 当前模块中的全局变量
- python内置变量
比如:
a=1
def test(x):
global x
a=x
因为a外层变量是全局变量,所以要加global
def test2():
a=1
def test(x)
nonlocal x
a=x
因为a外层变量不是是全局变量,也是一个外层的局部变量,所以要加nonlocal
python 在新建一个变量时,默认作用域为当前局部作用域。如果不声明global or nonglocal,就认为是一个局部变量。
内部函数,不修改外层变量可以访问外层变量。
a = 1
def fun():
print(a) # 在函数内部找不到对 a 的定义,则去外层查询。输出1。
fun()
内部函数,修改同名外层变量,则python会认为是定义了一个新的局部变量,与外层变量无关了。
a = 1
def fun():
a = 2 # 声明了一个局部变量,与外面等于1的那个a没有关系了
print(a) # 输出2
fun()
print(a) # 输出1
在内部函数修改同名全局变量之前调用变量名称,则引发Unbound-LocalError
a = 1
def fun():
print(a) # 先引用
a = 2 # 再修改
fun()
如果我们想要强制访问外层变量 a,便可以使用 global 关键字
a = 1
def fun():
global a # a为全局变量
print(a) # 输出1
a = 2 # 改变的是全局变量,因此出了这个局部作用域,仍然有效
fun()
print(a) # 输出2
注意,这个时候,不要将 global 换为 nonlocal 关键字,不然会报错:
这是因为 nonlocal 表示外层变量,但是一旦外层变量是全局变量,则只能用 global。如果将这段代码全部放到一个函数中,则可以使用 nonlocal :
def outer_fun():
a = 1
def fun():
nonlocal a # a为外层变量
print(a) # 输出1
a = 2
fun()
print(a) #输出2
outer_fun()
注意:可以发现,之前的将 global 换为 nonlocal 的报错,和这次的将 nonlocal 改为 global 的报错,错误类型是不同的。前者是 nonlocal a 这一行报错,后者是 print(a) 这一行报错。也就是说,在使用 nonlocal a 之前,必须保证外层的确已经定义过 a 了,但是在 global a 的时候,可以允许全局变量中还没有定义过a,可以留在后面定义。比如将 print(a) 之前加上对a的定义,便不会出错:
def outer_fun():
a = 1
def fun():
global a # a为全局变量,与上面等于1的 a 没有关系
a = 3 # 定义全局变量
print(a) # 输出3
a = 2
fun()
print(a) #输出1,局部变量
outer_fun()
print(a) # 输出2,全局变量