关于python中的nonlocal关键字

如果在函数的子函数中需要调用外部变量,一般会看见一个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。
这个时候运行会出现报错:
关于python中的nonlocal关键字_第1张图片
到上面为止都很容易理解。
但是迷惑的点在于我经常看见子函数应用外部变量,但没有进行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 或者返回修改后的值并重新赋给外部变量。

需要注意的事,就算在函数内部引用一个外部的可变对象变量,如果涉及到对该变量的重新赋值,也需要加nonlocal

def outer_function():
    x = [1,2,3]

    def inner_function():
        nonlocal  x
        x = x+[2]
        # x.append(2)
        print(x)

    inner_function()

outer_function()
def outer_function():
    x =  [1,2,3]

    def inner_function():
        # nonlocal  x
        # x = x+[2]
        x.append(2)
        print(x)

    inner_function()

outer_function()

要理解这两者的区别,关键是对于x = []这句的理解,在这里,x 是一个变量,它存储了对列表 [1, 2, 3] 的引用。这表示 x 指向了内存中存储这个列表的位置。而x + [2] 创建了一个新的列表 [1, 2, 3, 2],然后将这个新列表赋给了变量 x。现在,变量 x 指向了一个新的列表对象,发生了重新赋值。所以存在这种重新赋值的情况时,需要加一个nonlocal,这样才能在子函数外部接收到。

你可能感兴趣的:(python,开发语言)