如果在函数的子函数中需要调用外部变量,一般会看见一个nonlocal声明,类似下面这种:
def outer_function():
x = 10
def inner_function():
nonlocal x
x += 1
print(x)
inner_function()
outer_function()
在这个例子中,inner_function 引用了外部函数 outer_function 中的变量 x,并对其进行了修改。由于涉及修改外部函数的变量,所以需要使用 nonlocal 关键字。
如果在 inner_function 中不使用 nonlocal,而直接对 x 进行修改,Python 将认为 x 是一个新的局部变量,并在 inner_function 中创建一个新的局部变量 x,而不会修改外部函数 outer_function 中的 x。
这个时候运行会出现报错:
到上面为止都很容易理解。
但是迷惑的点在于我经常看见子函数应用外部变量,但没有进行nonlocal的声明,比如下面这种:
def outer_function():
x = [10]
def inner_function():
x.append(2)
print(x)
inner_function()
outer_function()
这里inner_function 也引用了外部函数 outer_function 中的变量 x,并对其进行了修改,但并没有声明nonlocal,这是为什么?
原因是:
在这个特定的情况下,x是一个可变对象(列表),而不是不可变对象。在 Python 中,对于可变对象(如列表、字典等),可以在不使用 nonlocal 的情况下在函数内部修改它们的值,因为它们是通过引用传递的。
当你在函数内部修改一个可变对象时,实际上是在原地修改这个对象,而不是重新绑定变量。因此,对于列表 x,你可以在函数内部追加或删除元素,而无需使用 nonlocal。
如果 x是一个不可变对象,例如数字、字符串或元组,你将需要使用 nonlocal 关键字,因为对于不可变对象,重新绑定变量是唯一的方式来修改它们的值。
总的来说,对于可变对象,你可以在函数内部修改它们的值,而不需要 nonlocal 关键字。而对于不可变对象,你通常需要使用 nonlocal 或者返回修改后的值并重新赋给外部变量。