# global 和 nonlocal
# 定义一个不可变变量b 并试图先输出在更改b的值
b = 5
def func(a):
print(a)
print(b)
b += a
4
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
<ipython-input-3-74f9771a5f0e> in <module>()
----> 1 func(a = 4)
<ipython-input-1-c4bb2c5c9e48> in func(a)
4 def func(a):
5 print(a)
----> 6 print(b)
7
8 b += a
UnboundLocalError: local variable 'b' referenced before assignment
此时在print(b) 的时候就会抛出异常
因为在输出b的时候,由于在函数内部试图更改b的值,
所以在打印b的时候会从函数内部局域寻找变量b的值,然而发现并没有给b赋值,所以抛出异常
b = 5
def func(a):
global b
print(a)
print(b)
b += a
# 在函数内部给b加上global关键字后 ,更改b, 成功输出
func(a = 4)
print(b)
4
5
9
# 加入global后,使得生存于全局作用域的b得以在函数其中被改变,否则这些不可变变量如b 将只能读不能更改
# 但是可变变量如列表 可以在任何位置被更改(如果被定义为全局变量的话)。
# nonlocal
# 理解nonlocal之前先理解 闭包 的概念
# 闭包: 是一种函数,可以保留定义函数时候存在的一些自由变量
# 例如, 有这样一种场景:不断计算新加进来数同前面已经存在数的和。 这个题目可以理解为,已经存在数的和为这个函数的自由变量, 利用闭包来实现
def func_add():
sum = 0
def add_newnum(new_num):
nonlocal sum
sum += new_num
print("sum:---%r"%sum)
return add_newnum
# 调用闭包
cal_sum = func_add()
cal_sum(2)
输出:sum:---2
cal_sum(5)
输出:sum:---7
cal_sum(4)
输出:sum:---11
# 注意到在add_newnum 内层函数中,使用了nonlocal ,他的作用主要是使得外层的变量称为自由变量
# 可以同global一样理解,不过应用场景不同, nonlocal主要应用于这种函数嵌套的内部。
# 闭包为什么能够保留已经存在的自由变量呢?
# 当调用 cal_sum = func_add由于fun_add 函数返回的是内层函数名:add_newnum
# 所以调用cal_sum(2) 相当于调用 add_newnum(2) 但是add_newnum始终是func_add返回的,所以如果不更改add_newnum
# 的引用,将始终保持着cal_sum 和 fun_add的关系,则fun_add里面的自由变量sum的值也就会被更改并保存
# 如果更改func_add的引用,如
add_sum2 = func_add()
add_sum2(4)
# 此时又会创建另一份函数作用空间, 自由变量sum的值将从0开始重新被调用更改。
输出:sum:---4