我们知道python中的变量(variable)的作用域(scope)取决于该变量在源代码的何处被赋值。一般而言,变量在三种不同的位置被赋值,对应如下的三种作用域:
前两种是很容易理解的:变量在函数外被赋值,作用域即为global,也就能被.py文件中的所有函数访问;变量在某个函数内被赋值,就是那个函数的本地变量,也只能在该函数内部进行访问。
第三种作用域其实是第二种作用域的特殊情况,也即nonlocal scope 是特殊的local scope。要理解nonlocal scope,首先我们应明白函数是可以嵌套定义的,比如下面这样
def outer_func():
inner_num = 813
def inner_func1():
print(f"I'm func1, inner number is {inner_num}")
return inner_func1
inner_func = outer_func()
inner_func()
上面的例子中,inner_num这个变量在outer_func内部、inner_func1的外部被定义,即,对于outer_func来说它是一个local variable,对于inner_func1来说它是一个nonlocal variable。那么函数能否访问自己的nonlocal variable呢?答案是肯定的(可以运行一下上面的代码试试)。
需要注意的是,在内嵌函数中修改非本地变量,正如在函数中访问全局变量一样,需要有一个关键字声明,前者是nonlocal,后者是global
def outer_function():
x = 10 # 局部变量 x
def inner_function():
nonlocal x # 声明 x 为非本地变量
x += 5 # 修改 x 的值
print("Inner function:", x)
inner_function()
print("Outer function:", x)
outer_function()
以上代码的结果是
Inner function: 15
Outer function: 15
如果未声明nonlocal x,运行程序会出现以下报错
UnboundLocalError: local variable 'x' referenced before assignment
即编译器认为x是内嵌函数的local variable,但这个变量在引用之前就赋值了。
因此,无论是inner function(nested function)中访问和修改nonlocal variable,最好都先用nonlocal进行声明。