LEEFEI571 发表于 7 天前

嵌套函数里的nonlocal语句和global语句混合使用的问题

我写了一个三层嵌套函数,每层嵌套函数里均只有一个x变量,我想通过nonlocal语句从最里层的嵌套函数中的x值(101112)逐层修改上一层函数中的x值,到达最外层函数时再通过global语句修改全局变量x的值(123),,使全局变量x的值由123变为101112,我的执行代码附上,但在程序执行时却出现报错,报错截图如下:

x = 123

def level1():
    global x
    x = 456
    print(f'在第一层函数中x的值是{x},相应的id值是{id(x)}')
    def level2():
      nonlocal x
      x = 789
      print(f'在第二层函数中x的值是{x},相应的id值是{id(x)}')
      def level3():
            nonlocal x
            x = 101112
            print(f'在第三层函数中x的值是{x},相应的id值是{id(x)}')
      level3()
      print(f'在第三层函数中声明nonlocal语句后,第二层x的值变为{x},相应的id值变为{id(x)}')
    level2()
print(f'在第二层函数中声明nonlocal语句后,第二层x的值变为{x},相应的id值变为{id(x)}')

麻烦大神指点为何报错,以及如何修改全局变量x的值,谢谢!!!

FishC 发表于 7 天前

在Python中,`nonlocal`语句用于在嵌套函数中绑定外层函数的变量,而`global`语句用于绑定全局作用域的变量。你遇到的错误是因为试图对`global`后的变量应用`nonlocal`,这在Python中是不允许的。

在你的例子中,`level1()`中的`x`是全局变量,因为你用了`global`关键字,所以`level2()`和`level3()`无法通过`nonlocal`访问到`level1()`定义的同名变量`x`。因此,`level2()`和`level3()`中的`nonlocal x`会引发一个错误。

要实现你想要的效果,不需要在`level1()`中使用`global`和`nonlocal`,而是可以直接修改最外层的`x`。代码可以简化如下:

x = 123

def level1():
    def level2():
      def level3():
            global x
            x = 101112
            print(f'在第三层函数中x的值是{x},相应的id值是{id(x)}')
      level3()
      print(f'在第二层函数中x的值是{x},相应的id值是{id(x)}')
    level2()

level1()
print(f'全局变量x的最终值为{x},相应的id值是{id(x)}')

在这个改进后的代码中,我们直接在`level3()`中使用`global x`来修改全局变量`x`的值,而不在中间的`level1()`和`level2()`中重新定义`x`,这样就避免了`nonlocal`和`global`同时使用的问题。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

jackz007 发表于 7 天前

本帖最后由 jackz007 于 2024-12-14 22:46 编辑

      使用 nonlocal x 声明的变量 x 应该是外层函数中的一个局部变量,在本例中, level2() 中被声明为 nonlocal 的变量 x 在其外层函数 level1() 中被声明为 global,既然 x 在 level1() 中已经被声明为 global 了,那么,在其内嵌函数 level2()、level3() 中就不可以将 x 声明为 nonlocal,而应该继续声明为 global,这样,无论在 level1()、level2() 还是 level3() 中修改 x 的值,修改的实际上是同一个对象 x。

x = 123

def level1():
    global x
    x = 456
    print(f'在第一层函数中x的值是{x},相应的id值是{id(x)}')
    def level2():
      global x
      x = 789
      print(f'在第二层函数中x的值是{x},相应的id值是{id(x)}')
      def level3():
            global x
            x = 101112
            print(f'在第三层函数中x的值是{x},相应的id值是{id(x)}')
      level3()
      print(f'在第三层函数中声明 global 语句后,第二层x的值变为{x},相应的id值变为{id(x)}')
    level2()
print(f'在第二层函数中声明 global 语句后,第二层x的值变为{x},相应的id值变为{id(x)}')

level1()

LEEFEI571 发表于 7 天前

jackz007 发表于 2024-12-14 22:37
使用 nonlocal x 声明的变量 x 应该是外层函数中的一个局部变量,在本例中, level2() 中被声明为 no ...

Jack兄,
请教一下如果我有一个多层嵌套函数(比如这个例子中的三层嵌套函数),如果想通过最内层的函数修改变量并传递回上一层(比如在level3中对x变量进行加工,然后传递回level2),然后继续修改并再传递回上一层(在level2中对x变量继续加工,然后传递回到level1),到达最外层后进行最后的加工然后将x变量的值传递出去成为覆盖全局变量x原先的值(在level1中对x变量继续加工,最后然后传递出函数,覆盖全局变量x原先的值),这该如何实现?

jackz007 发表于 7 天前

LEEFEI571 发表于 2024-12-14 22:51
Jack兄,
请教一下如果我有一个多层嵌套函数(比如这个例子中的三层嵌套函数),如果想通过最内层的函数修改 ...

      只需要在所有的嵌套函数内外都使用同一个变量标识(比如,x),并且,在各级函数中,都要把这个变量声明为全局变量(global x),这样,无论函数内外,使用到的都将是同一个变量(x),无论在任何位置,只要对该变量(x)进行修改,在所有的函数内外(只限于声明过 global x 的函数),都会接收到这个修改,因为,从本质上说,它们所使用的都是同一个对象(x)。

LEEFEI571 发表于 6 天前

jackz007 发表于 2024-12-14 23:36
只需要在所有的嵌套函数内外都使用同一个变量标识(比如,x),并且,在各级函数中,都要把这个 ...

明白了,非常感谢Jackz兄指点,感谢一路有你指教!!!
页: [1]
查看完整版本: 嵌套函数里的nonlocal语句和global语句混合使用的问题