鱼C论坛

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

[已解决]20课课后题6

[复制链接]
发表于 2018-7-15 10:34:28 | 显示全部楼层 |阅读模式

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

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

x
>>> def fun1():
        x=5
        def fun2():
                nonlocal x
                x+=1
                return x
        return fun2

>>> a=fun1()
>>> a()
6
>>> a()
7
>>> fun1()()
6
>>> fun1()()
6

既然fun1()赋值给a,那标签a和fun1()不就是等同的吗?为什么结果不一样
下面解释也没看懂,函数被释放是什么意思

最佳答案
2018-7-15 12:44:32
dronemodel 发表于 2018-7-15 11:32
fun1虽然不执行,但每次nonlocal x的时候x都是从fun1里找?

fun1执行完毕后,解释器就自动回收了,但是x由于被fun2引用,不会被回收。除了第一次的x来自fun1里的定义,后面的x已与fun1无关,但对fun2来说,x始终是函数外变量
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-7-15 11:14:18 | 显示全部楼层
本帖最后由 凌九霄 于 2018-7-15 11:22 编辑

a跟fun1不等同,fun1()()执行的时候,x每次会被初始化为5,但是a执行的是fun2,是闭包,fun1执行后被释放,但是x值因为fun2的引用被保留,所以每次执行a()是一个累加的效果
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-7-15 11:19:05 | 显示全部楼层
凌九霄 发表于 2018-7-15 11:14
a跟fun1不等同,fun1()()执行的时候,x每次会被初始化为5,但是a执行的是fun2,fun1已被释放,所以每次执行 ...

fun1被释放是什么意思呢?
每次执行a()的时候fun1()不参与吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-7-15 11:23:46 | 显示全部楼层
本帖最后由 凌九霄 于 2018-7-15 11:26 编辑
dronemodel 发表于 2018-7-15 11:19
fun1被释放是什么意思呢?
每次执行a()的时候fun1()不参与吗?


是的,fun1不再参与,a指向的是fun2函数的地址,每次执行的是fun2
  1. def fun1():
  2.     x = 5
  3.     print('我是fun1')
  4.     def fun2():
  5.         nonlocal x
  6.         x += 1
  7.         return x

  8.     return fun2
复制代码


稍改动一下,你会发现,除了第一次,print不再被执行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-7-15 11:32:24 | 显示全部楼层
fun1虽然不执行,但每次nonlocal x的时候x都是从fun1里找?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-7-15 12:44:32 | 显示全部楼层    本楼为最佳答案   
dronemodel 发表于 2018-7-15 11:32
fun1虽然不执行,但每次nonlocal x的时候x都是从fun1里找?

fun1执行完毕后,解释器就自动回收了,但是x由于被fun2引用,不会被回收。除了第一次的x来自fun1里的定义,后面的x已与fun1无关,但对fun2来说,x始终是函数外变量
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-7-15 13:01:37 | 显示全部楼层
凌九霄 发表于 2018-7-15 12:44
fun1执行完毕后,解释器就自动回收了,但是x由于被fun2引用,不会被回收。除了第一次的x来自fun1里的定义 ...

谢谢!懂了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-7-15 13:06:45 | 显示全部楼层
这里的a=fun1()不是把fun1()赋值给a,而是把fun1()这个函数实例化为a,这里的a并不是代表函数fun1(),这里的a代表的仅仅是带有fun1功能的他自己而已。
打一个比喻:这里比喻fun1()是人这个物种,a=fun1()相当于一个出生的宝宝a,a他自己长大变化了但是不代表fun1()这个物种也在变化,所以每个新出生的fun1()仍然是最原始的样子。
不知道这个比喻你能不能理解
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-7-18 09:26:35 | 显示全部楼层
本帖最后由 凌九霄 于 2018-7-18 09:27 编辑

查了下资料,发现我原来的回答是有问题的。正确的应该是,对于闭包来说,其环境变量会保存在函数对象的__closure__属性中
  1. def fun1():
  2.     x = 5
  3.   
  4.     def fun2():
  5.         nonlocal x
  6.         x += 1
  7.         return x

  8.     return fun2

  9. #在上面的例子中,fun1执行完后,系统回收,但是x由于被fun2引用,其值保存在fun2的__closure__属性中,__closure__里包含了一个元组(tuple),这个元组中的每个元素是cell类型的对象.
  10. #用以下代码可以取到这个值
  11. A = fun1()
  12. print(A.__closure__[0].cell_contents)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-7-19 11:19:32 | 显示全部楼层
凌九霄 发表于 2018-7-18 09:26
查了下资料,发现我原来的回答是有问题的。正确的应该是,对于闭包来说,其环境变量会保存在函数对象的__cl ...

谢谢!
我现在还没学到属性
以后再来看!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-3-29 20:23

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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