这两者都只有在修改外部作用域变量时才需要,如果只是读取就不用
首先需要区分python中的全局变量和局部变量
全局变量是在函数外定义的变量,即所有定义在def
中的变量都不是全局变量,即使是嵌套函数外层函数中定义的变量
相反,定义在函数内部的变量即为局部变量,即使闭包嵌套再多层,也都是局部变量。
如果要在函数中 修改 全局变量(即将原本的引用指向一个新的引用地址,最下面有举例说明),则需要先用 global
声明。
count = 0
def increment():
global count # 修改全局变量前应先声明这里的count是全局变量,否则下一行语句会报错
count += 1
print(count)
increment() # 输出1
increment() # 输出2
如果想要在闭包中修改上层函数中的变量,则需要使用 nonlocal
关键字先声明,它的作用和 global
类似,但是它只能关联嵌套函数中上层函数中的变量。
def outer():
count = 0
def increment():
nonlocal count # 使用nonlocal声明这里的count是上层函数中的count
count += 1
print(count)
increment() # 输出1
increment() # 输出2
outer()
注意:即使上层函数中没有引用的变量,但是上上层有,或者更上层有,也是可以的:
def outer():
count = 0
def inner():
def increment():
nonlocal count # 使用nonlocal声明这里的count是上上层函数中的count
count += 1
print(count)
increment() # 输出1
increment() # 输出2
inner()
outer()
但是nonlocal引用的变量必须是局部变量(定义在函数内部),如果将上述 count=0
定义在最上层(outer()函数外面),则报错。
那么global和nonlocal可不可以组合使用呢?考虑下面代码:
count = 0
def outer():
global count
def increment():
nonlocal count
count += 1
print(count)
increment() # 报错:no binding for nonlocal 'count' found
outer()
还是那句话,nonlocal引用的变量必须是局部变量,上面的代码中虽然在outer()函数中使用 global 引用了全局变量 count,但它本质上还是全局变量。
所有,要使得上述代码正确运行。只需要将 increment()
函数中的 nonlocal count
修改为 global count
即可
考虑以下代码,他们执行时会报错吗?
def f():
count = 0
def s():
count = count + 1
s()
def f():
count = 0
def s():
count = 1
s()
def f():
arr = [1]
def s():
arr.append(2)
s()
第一个会报错,后两个不会报错,原因是:
对于第二个代码:两个count是两个变量,s()函数中的count是单独创建的一个变量,而使用 += 这种操作符时就不会重新创建变量
对于第三个代码:并没有改变arr的引用,只是在原本引用的数组上添加了一个元素而已,所以 f()函数中的arr最终为 [1, 2]