鱼C论坛

 找回密码
 立即注册
查看: 1147|回复: 2

[已解决]对闭包的疑惑

[复制链接]
发表于 2024-1-4 23:33:35 | 显示全部楼层 |阅读模式

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

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

x
想问一下要怎么理解闭包呢,比如在下面的程序中,为啥move(-2,2)是在原有(x=1,y=2)的情况下移动,而不是(x=0,y=0)呢?

>>> 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
最佳答案
2024-1-5 10:15:44
在Python中,闭包是由函数以及创建该函数时存在的自由变量的环境组成的实体。

当鱼油在一个函数内部定义另一个函数,并且内部函数引用了外部函数的变量时,就创建了一个闭包。

在图中的例子中,outer 函数定义了变量 x 和 y,然后定义了内部函数 inner。

inner 函数通过使用 nonlocal 关键字声明,它将引用并可以修改 outer 函数的局部变量 x 和 y。

当 outer 函数被调用并返回 inner 函数时,它实际上返回了一个闭包。

这个闭包记住了 x 和 y 的当前值,即使在 outer 函数的执行上下文已经结束之后。

因此,当您第一次调用 move(1,2) 时,它更新了 x 和 y 的值。

由于闭包记住了这些值,当您再次调用 move(-2,2) 时,它是在已更新的 x 和 y 值的基础上进行操作的。

这就是为什么 move(-2,2) 的调用是在 x=1, y=2 的情况下移动的,而不是从 x=0, y=0 开始。

每次调用 move 实际上都是在修改同一闭包环境中的 x 和 y,这个环境是在第一次调用 outer() 并赋值给 move 时创建的。
8.jpg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-1-4 23:34:52 | 显示全部楼层
闭包是指一个函数内部定义的函数,它可以访问外部函数的局部变量,并把这些局部变量保存在自己的环境中。在你的代码中,outer函数返回了inner函数,而inner函数引用了outer函数的局部变量x和y。

当你调用outer函数时,它会创建一个新的inner函数,并将这个函数赋值给move变量。此时,outer函数内部的局部变量x和y被存储在inner函数的环境中,形成了一个闭包。

当你调用move(1,2)时,inner函数会使用它自己的环境中的x和y变量进行计算,并打印结果。此时,x加1,y加2,所以输出为"x=1,y=2"。

然后,当你调用move(-2,2)时,inner函数仍然使用自己的环境中的x和y变量进行计算,并打印结果。此时,内部变量x减2,y加2,所以输出为"x=-1,y=4"。

总结一下,由于闭包具有记忆效应,inner函数在多次调用时会保持对outer函数内部局部变量的引用,而不会重新初始化这些变量。因此,move函数在每次调用时都会在之前的基础上进行偏移,而不是从初始位置开始。

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

使用道具 举报

发表于 2024-1-5 10:15:44 | 显示全部楼层    本楼为最佳答案   
在Python中,闭包是由函数以及创建该函数时存在的自由变量的环境组成的实体。

当鱼油在一个函数内部定义另一个函数,并且内部函数引用了外部函数的变量时,就创建了一个闭包。

在图中的例子中,outer 函数定义了变量 x 和 y,然后定义了内部函数 inner。

inner 函数通过使用 nonlocal 关键字声明,它将引用并可以修改 outer 函数的局部变量 x 和 y。

当 outer 函数被调用并返回 inner 函数时,它实际上返回了一个闭包。

这个闭包记住了 x 和 y 的当前值,即使在 outer 函数的执行上下文已经结束之后。

因此,当您第一次调用 move(1,2) 时,它更新了 x 和 y 的值。

由于闭包记住了这些值,当您再次调用 move(-2,2) 时,它是在已更新的 x 和 y 值的基础上进行操作的。

这就是为什么 move(-2,2) 的调用是在 x=1, y=2 的情况下移动的,而不是从 x=0, y=0 开始。

每次调用 move 实际上都是在修改同一闭包环境中的 x 和 y,这个环境是在第一次调用 outer() 并赋值给 move 时创建的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-9-21 22:52

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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