鱼C论坛

 找回密码
 立即注册
查看: 1188|回复: 6

[已解决]函数内包课后习题的问题

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

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

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

x
本帖最后由 Jerry~Mouse 于 2021-8-27 22:19 编辑

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
应该说还是没有明白funY后面不加()的意义
最佳答案
2021-8-28 10:33:55
本帖最后由 白two 于 2021-8-28 10:45 编辑
Jerry~Mouse 发表于 2021-8-28 01:10
难道说a = funx() 这个语句是不执行funY里面的内容的吗,仅仅就是把a指向了funY?其实此时x 还是= 5?
...


funY 哪来的值呢?他只是一个函数罢了
可以这么理解,但我感觉它的机制像是重新给 a 开辟了一块内存来存储 funY 的逻辑:
def funX():
    x = 5
    def funY():
        nonlocal x
        x += 1
        return x
    return funY

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

b = funX()
c = funX()
print(funX())
print(b)
print(c)
print(id(b))
print(id(c))

print(b())
print(b())
print(c())

结果:
1363293958208
1363293958208
<function funX.<locals>.funY at 0x0000013D6B18A3A0>
<function funX.<locals>.funY at 0x0000013D6B188E50>
<function funX.<locals>.funY at 0x0000013D6B18A310>
1363301404240
1363301409552
6
7
6

你看,三个函数funx(),b,c,全是 function funX.<locals>.funY 对象,只是地址不一样罢了,

你看如果直接 a = funX 的话,就是 a 指向 funX 的内存,调用 a 改的 x 是啥值, funX 的 x 就是啥值
但是闭包的话就相当于再开了一块内存,但是函数依然是 funY ,所以 x 初始值依然是 5,但 b,c的内存地址不一样,所以它俩互不影响,但是你是直接三次调用 a 啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-8-27 23:27:57 | 显示全部楼层
本帖最后由 白two 于 2021-8-27 23:38 编辑

将函数作为返回值是高阶函数,称为闭包
带括号,调用的是函数的return结果,需要等待函数执行完成的结果
不带括号时,调用的是这个函数本身 ,是整个函数体,是一个函数对象,不需等该函数执行完成
funX() 函数 return 的是 funY 函数的一个引用,这个时候就像但与 a 指向这个函数的本体, a 就相当于 funY , a() 就相当于 funY()
def funX():
    x = 5
    def funY():
        nonlocal x
        x += 1
        return x
    print(funY)
    return funY

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

结果:
<function funX.<locals>.funY at 0x00000213E7F19E50>
6
7
8
<function funX.<locals>.funY at 0x00000213E7F19E50>

你看 a 和 funY 指向的是同一个函数对象
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-28 01:02:38 | 显示全部楼层
白two 发表于 2021-8-27 23:27
将函数作为返回值是高阶函数,称为闭包
带括号,调用的是函数的return结果,需要等待函数执行完成的结果
...

其实我这道题不解的是,第一次a = funx()执行完之后,a返回了一个函数,funY,这个funY的值永远是6,我就觉得后面无论怎么调用这个a(),它的值都应该是funY调用出来的结果,永远都为6
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-28 01:10:52 | 显示全部楼层
本帖最后由 Jerry~Mouse 于 2021-8-28 01:22 编辑
白two 发表于 2021-8-27 23:27
将函数作为返回值是高阶函数,称为闭包
带括号,调用的是函数的return结果,需要等待函数执行完成的结果
...


难道说a = funx() 这个语句是不执行funY里面的内容的吗,仅仅就是把a指向了funY?其实此时x 还是= 5?
然后a()就表示 我现在开始调用funY这个函数了 到现在为止x才开始变化?此时x才变为了6?
然后再下面的a()就是从x = 6的基础上调用funY这个函数的吗?
我可以这样理解吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-8-28 10:33:55 | 显示全部楼层    本楼为最佳答案   
本帖最后由 白two 于 2021-8-28 10:45 编辑
Jerry~Mouse 发表于 2021-8-28 01:10
难道说a = funx() 这个语句是不执行funY里面的内容的吗,仅仅就是把a指向了funY?其实此时x 还是= 5?
...


funY 哪来的值呢?他只是一个函数罢了
可以这么理解,但我感觉它的机制像是重新给 a 开辟了一块内存来存储 funY 的逻辑:
def funX():
    x = 5
    def funY():
        nonlocal x
        x += 1
        return x
    return funY

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

b = funX()
c = funX()
print(funX())
print(b)
print(c)
print(id(b))
print(id(c))

print(b())
print(b())
print(c())

结果:
1363293958208
1363293958208
<function funX.<locals>.funY at 0x0000013D6B18A3A0>
<function funX.<locals>.funY at 0x0000013D6B188E50>
<function funX.<locals>.funY at 0x0000013D6B18A310>
1363301404240
1363301409552
6
7
6

你看,三个函数funx(),b,c,全是 function funX.<locals>.funY 对象,只是地址不一样罢了,

你看如果直接 a = funX 的话,就是 a 指向 funX 的内存,调用 a 改的 x 是啥值, funX 的 x 就是啥值
但是闭包的话就相当于再开了一块内存,但是函数依然是 funY ,所以 x 初始值依然是 5,但 b,c的内存地址不一样,所以它俩互不影响,但是你是直接三次调用 a 啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-28 19:02:23 | 显示全部楼层
白two 发表于 2021-8-28 10:33
funY 哪来的值呢?他只是一个函数罢了
可以这么理解,但我感觉它的机制像是重新给 a 开辟了一块内存来存 ...

所以b = funx()和c = funx()
这两个funx()不一样对吧,就如同
a = [1,2,3]
b = [1,2,3]
这两个列表互不干涉,是这个意思吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-8-28 20:25:56 | 显示全部楼层
Jerry~Mouse 发表于 2021-8-28 19:02
所以b = funx()和c = funx()
这两个funx()不一样对吧,就如同
a = [1,2,3]


嗯,相当于复刻了一份 funY
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-13 13:18

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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