鱼C论坛

 找回密码
 立即注册
查看: 564|回复: 9

[学习笔记] 函数中nonlocal的用法

[复制链接]
发表于 2024-8-5 17:19:14 | 显示全部楼层 |阅读模式

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

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

x
B站46讲小甲鱼降到了nonlocal的用法,感觉不是很理解。百度了一下,感觉讲的也是玄之又玄的。其实我觉得很简单啦,以下面的代码为例。
原来“x, y”只能作用于函数outer(),地盘就在第一层函数,在第二层提他没用,见代码1。使用nonlocal之后“x,y”的地盘扩大到了第二层,提他也有用,见代码2。

代码1:
def outer():
    x=0
    y=0
    def inner(x1, y1):
        x+=x1
        y+=y1
        print(f"Now, x={x}, y={y}")
    return inner

move = outer()
move(1, 2)
Traceback (most recent call last):
  File "<pyshell#76>", line 1, in <module>
    move(1, 2)
  File "<pyshell#74>", line 5, in inner
    x+=x1
UnboundLocalError: cannot access local variable 'x' where it is not associated with a value


代码2:
>>> def outer():
...     x = 0
...     y = 0
...     def inner(x1, y1):
...         nonlocal x, y
...         x +=x1
...         y +=y1
...         print(f"现在, x = {x}, y = {y}")
...     return inner
... 
>>> move = outer()
>>> move(1, 2)
现在, x = 1, y = 2
>>> move(-2, 2)
现在, x = -1, y = 4

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-8-5 17:20:30 | 显示全部楼层
哈哈,看来你已经很接近理解`nonlocal`的用法了!让我们来用一个简单易懂的比喻,再加点幽默,让这个概念更加清晰吧。

想象一下,你家的厨房(`outer`函数)里有一台非常特别的冰箱(`inner`函数),里面存放着食材(变量`x`和`y`)。这台冰箱是你的,但在厨房外面(在`inner`函数内),如果你需要增添食材,你必须要告诉冰箱“嘿,我想把这些食材(参数`x1`和`y1`)放进你这里!”否则,冰箱会不知所措,反而提示你“我不知道你说的是什么,你给我的东西可没有在我的储藏室简单地找到!”

### 代码1:没有`nonlocal`
def outer():
    x = 0
    y = 0
    def inner(x1, y1):
        x += x1  # 这里的x是冰箱外面的(即外层函数的x),但是内层函数不知道
        y += y1  # 同理
        print(f"Now, x={x}, y={y}")
    return inner
在这种情况下,`inner`试图直接访问冰箱里的食材,但因为它不知道这些食材原本在哪里,所以就急得“UnboundLocalError”了!就像你进厨房想往冰箱里放东西,但冰箱说:“请先告诉我你是什么人!”

### 代码2:使用了`nonlocal`
def outer():
    x = 0
    y = 0
    def inner(x1, y1):
        nonlocal x, y  # 这是你告诉冰箱:“好吧,我就是你主人,可以使用你的食材!”
        x += x1  # 现在可以顺利增加x了
        y += y1  # 同理,增加y也没问题
        print(f"现在, x = {x}, y = {y}")
    return inner
在这种情况下,你通过`nonlocal`告诉了内层函数:“放心吧,x和y是我的,你可以使用这些食材!”结果嘛,冰箱(内层函数)就开心地把你买的食材(`x1`和`y1`)加进去了,并且能正确展示新的总数,不再俩人互相推诿。

所以,总结一下:
- 没有`nonlocal`,内层函数记不住外层函数的变量,就像你不能随便在厨房里取冰箱里的食材。
- 有了`nonlocal`,内层函数可以“合法”地使用外层函数的变量,就像你告诉冰箱,把食材交给你确认使用。

希望这个比喻能帮助你更轻松地理解`nonlocal`的用法!如果还有疑惑,随时问我哦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-8-5 17:44:21 | 显示全部楼层
其实就是改变变量的作用域。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-8-5 21:59:27 | 显示全部楼层
小甲鱼的二师兄 发表于 2024-8-5 17:44
其实就是改变变量的作用域。

是的,但是我看小甲鱼和百度AI都是说了一堆让人看了有点蒙的话
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-8-5 22:00:34 | 显示全部楼层
FishC 发表于 2024-8-5 17:20
哈哈,看来你已经很接近理解`nonlocal`的用法了!让我们来用一个简单易懂的比喻,再加点幽默,让这个概念更 ...

哈哈哈哈哈,我还是觉得你解释的有点复杂了,与Python的“极简”原则不符
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-8-5 22:00:44 | 显示全部楼层
William01 发表于 2024-08-05 22:00
哈哈哈哈哈,我还是觉得你解释的有点复杂了,与Python ...


哈哈,明白了!我们来一点“极简”的解释吧,保证简单明了,不扯更多的闲话!

### `nonlocal` 简单总结:

#### 1. **定义**:
`nonlocal` 是用来在嵌套函数中声明外层函数的变量,让内层函数可以直接修改这些变量。

#### 2. **用途**:
- 当你需要在内层函数里改变外层函数的变量时用`nonlocal`,而不是创建一个新的局部变量。

#### 3. **举个例子**:
def outer():
    x = 0  # 外层变量
    def inner():
        nonlocal x  # 声明要使用外层的x
        x += 1      # 修改外层的x
        print(x)    # 输出修改后的x
    inner()
    inner()

outer()  # 输出会是: 1, 2

### 4. **关键点**:
- **没有 `nonlocal`**:你不能修改外层的变量,只能读取!
- **有了 `nonlocal`**:可以随意修改外层的变量,内层就像拿到了“钥匙”!

这样懂了吗?简单干脆,如果还有问题就再问我哦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-8-5 22:03:02 | 显示全部楼层
FishC 发表于 2024-8-5 22:00
哈哈,明白了!我们来一点“极简”的解释吧,保证简单明了,不扯更多的闲话!

### `nonlocal` 简单 ...

呐,这就好多了,简单易懂。你很幽默,但是也没必要勉强的去幽默
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-8-5 22:06:19 | 显示全部楼层
William01 发表于 2024-08-05 22:03
呐,这就好多了,简单易懂。你很幽默,但是也没必要勉 ...


哈哈,收到!我会努力保持简单明了的风格,不过适度幽默也是为了让学习不那么乏味嘛!不过你说得对,最重要的是让你理解。如果你有任何问题或想讨论的内容,无论是代码还是其他的,随时来问我,我会竭尽所能帮你解答!继续加油哦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2024-8-27 18:20:01 | 显示全部楼层
第二层可以用第一层的变量,但是不能再对该变量进行更改了(没有用nonlocal的情况下)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-8-28 08:37:00 | 显示全部楼层
曾热爱这世界 发表于 2024-8-27 18:20
第二层可以用第一层的变量,但是不能再对该变量进行更改了(没有用nonlocal的情况下)

谢谢您的回复。不过,这样的话为什么还要定义第二层函数呢,没有意义的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-21 21:11

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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