鱼C论坛

 找回密码
 立即注册
查看: 1193|回复: 5

[已解决]关于nonlocal的疑惑

[复制链接]
发表于 2021-8-27 20:13:16 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
def fun1():
    x = 5
    def fun2():
        nonlocal x
        x *= 2        
        return x      
    return fun2()

这里的nonlocal会将外部变量x修改吗,还是会说,外部的x = 5 不会被修改,只会被调用?
最佳答案
2021-8-27 20:27:41
本帖最后由 叼辣条闯世界 于 2021-8-27 20:30 编辑

python官方是这样说的
非局部声明变量指代的已有标识符是最近外面函数的已声明变量,但是不包括全局变量。这个是很重要的,因为绑定的默认行为是首先搜索本地命名空间。nonlocal声明的变量只对局部起作用,离开封装函数,那么该变量就无效。

非局部声明不像全局声明,我们必须在封装函数前面事先声明该变量

非局部声明不能与局部范围的声明冲突


官网的解释虽然很好,但是不好理解,我们直接使用代码进行理解:


  1. count = 1

  2. def a():
  3.     count = 'a函数里面'    #如果不事先声明,那么函数b中的nonlocal就会报错
  4.     def b():
  5.         nonlocal count
  6.         print(count)
  7.         count = 2
  8.     b()
  9.     print(count)

  10. if __name__ == '__main__':
  11.     a()
  12.     print(count)
复制代码

结果是
a函数里面
2
1

该代码就可以很好的解释了,第一行的count和a()函数中的count是两个变量,而a()函数中的count变量只是在该函数内部起作用,因为它是一个局部变量。

nonlocal只能在封装函数中使用,在外部函数先进行声明,在内部函数进行nonlocal声明,这样在b()函数中的count与a()中的count是同一个变量。

nonlocal错误的使用方法

1.在外部函数进行声明

  1. count = 1

  2. def a():
  3.     #nonlocal count    #这种声明方法肯定报错,
  4.     def b():
  5.         nonlocal count    #在a()函数中没有提前声明,所以报错
  6.         print(count)
  7.         count = 2
  8.     b()
  9.     print(count)

  10. if __name__ == '__main__':
  11.     a()
  12.     print(count)
复制代码


报错代码:

  File "G:/python/test.py", line 5
    nonlocal count
    ^
SyntaxError: no binding for nonlocal 'count' found


2.外部函数中变量声明为global

  1. count = 1

  2. def a():
  3.     global count
  4.     count = 'a函数里面'
  5.     def b():
  6.         nonlocal count
  7.         print(count)
  8.         count = 2
  9.     b()
  10.     print(count)

  11. if __name__ == '__main__':
  12.     a()
  13.     print(count)
复制代码


报错代码:

  File "G:/python/test.py", line 7
    nonlocal count
    ^
SyntaxError: no binding for nonlocal 'count' found
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-8-27 20:24:47 From FishC Mobile | 显示全部楼层
这个语句会把内部和外部的x,变为一体,同时,如果内部x发生变化,会修改外部x
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2021-8-27 20:27:41 | 显示全部楼层    本楼为最佳答案   
本帖最后由 叼辣条闯世界 于 2021-8-27 20:30 编辑

python官方是这样说的
非局部声明变量指代的已有标识符是最近外面函数的已声明变量,但是不包括全局变量。这个是很重要的,因为绑定的默认行为是首先搜索本地命名空间。nonlocal声明的变量只对局部起作用,离开封装函数,那么该变量就无效。

非局部声明不像全局声明,我们必须在封装函数前面事先声明该变量

非局部声明不能与局部范围的声明冲突


官网的解释虽然很好,但是不好理解,我们直接使用代码进行理解:


  1. count = 1

  2. def a():
  3.     count = 'a函数里面'    #如果不事先声明,那么函数b中的nonlocal就会报错
  4.     def b():
  5.         nonlocal count
  6.         print(count)
  7.         count = 2
  8.     b()
  9.     print(count)

  10. if __name__ == '__main__':
  11.     a()
  12.     print(count)
复制代码

结果是
a函数里面
2
1

该代码就可以很好的解释了,第一行的count和a()函数中的count是两个变量,而a()函数中的count变量只是在该函数内部起作用,因为它是一个局部变量。

nonlocal只能在封装函数中使用,在外部函数先进行声明,在内部函数进行nonlocal声明,这样在b()函数中的count与a()中的count是同一个变量。

nonlocal错误的使用方法

1.在外部函数进行声明

  1. count = 1

  2. def a():
  3.     #nonlocal count    #这种声明方法肯定报错,
  4.     def b():
  5.         nonlocal count    #在a()函数中没有提前声明,所以报错
  6.         print(count)
  7.         count = 2
  8.     b()
  9.     print(count)

  10. if __name__ == '__main__':
  11.     a()
  12.     print(count)
复制代码


报错代码:

  File "G:/python/test.py", line 5
    nonlocal count
    ^
SyntaxError: no binding for nonlocal 'count' found


2.外部函数中变量声明为global

  1. count = 1

  2. def a():
  3.     global count
  4.     count = 'a函数里面'
  5.     def b():
  6.         nonlocal count
  7.         print(count)
  8.         count = 2
  9.     b()
  10.     print(count)

  11. if __name__ == '__main__':
  12.     a()
  13.     print(count)
复制代码


报错代码:

  File "G:/python/test.py", line 7
    nonlocal count
    ^
SyntaxError: no binding for nonlocal 'count' found
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2021-8-27 20:41:56 | 显示全部楼层
要能 "被修改",那肯定需要"被调用"呀。
因为你声明 x 是 nonlocal , 所以它会"往上找",找外层的x变量,找到了 fun1的局部变量 x ,发现x=5,可以用, 于是就用了。

所以,这里的修改操作 操作的就是 外部的x
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2021-8-27 21:31:19 | 显示全部楼层

外部函数中变量声明为global
为啥会报错?是因为global将外部变量申明为全局变凉了,所以nonlocal找不到外部变量了吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-8-27 23:46:57 | 显示全部楼层
Jerry~Mouse 发表于 2021-8-27 21:31
外部函数中变量声明为global
为啥会报错?是因为global将外部变量申明为全局变凉了,所以nonlocal找不到 ...

因为和global的声明 起冲突了。
nonlocal count 用的是外层的 count,
你再声明它同名的count是最外层的global,那就超出了nonlocal的"查找范围scope"了。
The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope. This is important because the default behavior for binding is to search the local namespace first. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope.

Names listed in a nonlocal statement, unlike to those listed in a global statement, must refer to pre-existing bindings in an enclosing scope (the scope in which a new binding should be created cannot be determined unambiguously).

Names listed in a nonlocal statement must not collide with pre-existing bindings in the local scope.
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 2 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-19 09:54

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表