鱼C论坛

 找回密码
 立即注册
查看: 2727|回复: 11

[已解决]第20课 习题6闭包问题

[复制链接]
发表于 2016-4-15 21:52:37 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 bp2018 于 2016-6-6 21:20 编辑

题目是:

def funX():
    x = 5
    def funY():
        nonlocal x
        x += 1
        return x
    return funY

a = funX()
print(a())
print(a())
print(a())

会打印:
6
7
8

给出的解释是:a=funX(),a没有重新被赋值,因此FunX()没被释放,因此局部变量x没有被初始化。

那么改为a=funX,如下:
def funX():
    x = 5
    def funY():
        nonlocal x
        x += 1
        return x
    return funY

a = funX
print(a()())
print(a()())
print(a()())

按照上述概念a也没有被重新赋值(不太懂?),为何打印结果是下面的数字呢?
6
6
6

感觉有点晕,请高手解答,谢谢!


最佳答案
2016-4-16 11:01:45
bp2018 发表于 2016-4-15 23:52
按照你的方法又看了看,还是定义a=funX,最后无论是输出id(a),或id(a()) 或 id(a()()), id是一样的?
...

a=funX, 这时候a指向的是函数对象funX,也就是:
  1. def funX():
  2.     x = 5
  3.     def funY():
  4.         nonlocal x
  5.         x += 1
  6.         return x
  7.     return funY
复制代码

注意:这时候只是用a指向函数对象,并没有调用,所以还没有返回funY这个函数对象.

而加了括号的a()是调用上面那个函数对象,这个函数返回另一个函数对象funY,每调用一次a()就返回1个新的函数对象,
  1. fun1 = a()
  2. fun2 = a()
  3. fun3 = a()

  4. print(id(fun1), id(fun2). id(fun3))
  5. print(fun1 == fun2 == fun3)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-4-15 22:51:57 | 显示全部楼层

a=funx,这时函数还没有执行啊,print的时候才开始执行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-4-15 23:15:08 | 显示全部楼层
在python中一切皆对象,函数也是对象,闭包函数返回的也是一个函数对象
在第一个例子中funX()只被调用了1次,也就是说只返回了1个函数对象,用变量a指向这个函数对象,可以在每个print后面跟踪一下id(a),可以看到a始终指向同1个函数对象,并没有改变过
再看看看第2个例子,a=funX,而a()被调用了3次,也就是返回的是3个不同的函数对象,实际上那段代码等同于:
  1. fun1 = a()
  2. print(fun1())
  3. fun2 = a()
  4. print(fun2())
  5. fun3 = a()
  6. print(fun3())
复制代码

再用id()函数看一下,fun1,fun2,fun3是3个不同的函数对象.
好比你定义了2个内容相同的函数:
  1. def f1(x):
  2.     return x
  3. def f2(x):
  4.     return x
  5. print(id(f1), id(f2))
复制代码

可以看到f1和f2虽然内容相同,但却是两个不同的函数对象.

评分

参与人数 1荣誉 +3 鱼币 +5 收起 理由
~风介~ + 3 + 5 支持楼主!

查看全部评分

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

使用道具 举报

发表于 2016-4-15 23:27:46 | 显示全部楼层
如果还想深入了解闭包,可以看一下关于python闭包函数的__closure__属性,闭包的环境变量就放在这个属性中,在你的第一个例子中,可以用a.__closure__[0].cell_contents查看环境变量x的值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-4-15 23:42:11 | 显示全部楼层
谢谢搂上2位,我再琢磨琢磨!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-4-15 23:52:27 | 显示全部楼层
本帖最后由 bp2018 于 2016-4-15 23:55 编辑
挥舞乾坤 发表于 2016-4-15 23:15
在python中一切皆对象,函数也是对象,闭包函数返回的也是一个函数对象
在第一个例子中funX()只被调用了1次, ...


按照你的方法又看了看,还是定义a=funX,最后无论是输出id(a),或id(a()) 或 id(a()()), id是一样的?

前面代码一样如下:

  1. def funX():
  2.     x = 5
  3.     def funY():
  4.         nonlocal x
  5.         x += 1
  6.         return x
  7.     return funY
复制代码



后面三者,print结果都是6,6,6 id相同
  1. a = funX
  2. print(a()(),id(a()))
  3. print(a()(),id(a()))
  4. print(a()(),id(a()))
复制代码

  1. a = funX
  2. print(a()(),id(a))
  3. print(a()(),id(a))
  4. print(a()(),id(a))
复制代码

  1. a = funX
  2. print(a()(),id(a()()))
  3. print(a()(),id(a()()))
  4. print(a()(),id(a()()))
复制代码


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

使用道具 举报

发表于 2016-4-16 00:12:17 | 显示全部楼层
funx()是内置函数 funx是变量 a=funx()和a=funx 完全不一样的两个概念吧 我也是新手 不知道对不对
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-4-16 11:01:45 | 显示全部楼层    本楼为最佳答案   
bp2018 发表于 2016-4-15 23:52
按照你的方法又看了看,还是定义a=funX,最后无论是输出id(a),或id(a()) 或 id(a()()), id是一样的?
...

a=funX, 这时候a指向的是函数对象funX,也就是:
  1. def funX():
  2.     x = 5
  3.     def funY():
  4.         nonlocal x
  5.         x += 1
  6.         return x
  7.     return funY
复制代码

注意:这时候只是用a指向函数对象,并没有调用,所以还没有返回funY这个函数对象.

而加了括号的a()是调用上面那个函数对象,这个函数返回另一个函数对象funY,每调用一次a()就返回1个新的函数对象,
  1. fun1 = a()
  2. fun2 = a()
  3. fun3 = a()

  4. print(id(fun1), id(fun2). id(fun3))
  5. print(fun1 == fun2 == fun3)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-4-16 15:16:03 | 显示全部楼层
挥舞乾坤 发表于 2016-4-16 11:01
a=funX, 这时候a指向的是函数对象funX,也就是:

注意:这时候只是用a指向函数对象,并没有调用,所以还没 ...

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

使用道具 举报

发表于 2016-4-19 16:08:23 | 显示全部楼层
谢谢答主指点
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-4-22 13:36:38 | 显示全部楼层
谢谢大神的解答!!!!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-7-18 12:55:36 | 显示全部楼层
谢谢大神的解答!!!!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-3-29 03:15

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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