shatanzongcai 发表于 2020-7-21 23:51:08

关于闭包的内存问题

各位鱼油晚上好,关于闭包我有一个非常不解的地方。我看了一个教程视频,讲者说闭包会有这样一个特性,就是闭包会保存外函数输入实参时的状态,不会被外函数传入新的实参所覆盖,具体例子如下def func(a,b):
   c = 10
   def func1():
         s = a+b+c
         print(s)
   return func1


x = func(5,6)
x()
y = func(3,4)
y()结果分别是21和17。如果分别打印id(x)和id(y)的话,可以看到x和y的内存地址是不一样的

讲者的解释是,因为传入的实参是数字,数字是不可变的,5和6,3和4被分配在了不同的内存上,那么x和y就一定在不同的内存上,因为内存不同,所以不会被相互覆盖

于是我觉得非常好奇,就做了以下操作
def func(a,b):
   c = 10
   def func1():
         s = a+b+c
         print(s)
   return func1


x = func(5,6)
print(id(x))
x()
y = func(5,6)
print(id(y))
y()

结果如下:
id(x) = 2643407263488
x() = 21
id(y) = 2643406349072
y() = 21

可以看到x()和y()的值是一样的,但是地址不同了。传入的参数明显是一样的,所以应该和传参的数据类型没关系。

我想知道的是:

1.这两组5和6是放在同一组内存上吗?如果是的话,那么x和y的地址就和参数的地址无关了,那么他们和谁有关?
2.如果这两组5和6不是放在同一地址上,那么为什么它们的地址不一样?很明显他们都是func()的局部参数。
3.闭包中的数据到底是如何写入内存的?


感谢各位鱼油。

Twilight6 发表于 2020-7-22 08:58:36



1.这两组5和6是放在同一组内存上吗?如果是的话,那么x和y的地址就和参数的地址无关了,那么他们和谁有关?

试试这段代码就知道是不是同一内存了:

def func(a, b):
    print(id(a),id(b))

x = func(5, 6)
y = func(5, 6)
输出结果:
140726224828320   140726224828352
140726224828320   140726224828352
可以看到内存地址相同

x 和 y 的地址和你设置的返回值有关系,而你设置的内置函数,就像局部变量一样,每个你返回的func1 都是互不关联的,所以 id 不同

2.如果这两组5和6不是放在同一地址上,那么为什么它们的地址不一样?很明显他们都是func()的局部参数。

x、y 传入的 5 和 6 id 是相同的,而返回的 func1 是互不关联的,因为这是属于这个函数内部的,类似于局部变量每次的作用空间都只在 func 函数内,而不在全局作用域,导致每次的 id 并不相同

3.闭包中的数据到底是如何写入内存的?

就是按照正常方式写入吧


°蓝鲤歌蓝 发表于 2020-7-22 10:50:15

我和楼上的意见一致,只是做一些补充。
x和y 的值 其实都是 func 函数返回的 func1,它们不相同的原因是 每次运行函数func内的代码时,会重新为func1分配地址。
说的明白一点就是在
x = func(5, 6)
时运行了 func() 函数,此时内部的 func1 被分配了一个地址。
同理
y = func(5, 6)
时也分配了一个地址。

shatanzongcai 发表于 2020-7-22 22:10:55

nahongyan1997 发表于 2020-7-22 11:29
python 对 1-100 之间的数字 的内存地址已经进行了固定已达到在引用时提升速度的目的,所以不管你的哪些变 ...

这个我已经知道了,但是我觉得这个不是我要问的问题,不过还是谢谢你的回答

shatanzongcai 发表于 2020-7-22 22:11:27

°蓝鲤歌蓝 发表于 2020-7-22 10:50
我和楼上的意见一致,只是做一些补充。
x和y 的值 其实都是 func 函数返回的 func1,它们不相同的原因是...

好的,我明白了,谢谢!

shatanzongcai 发表于 2020-7-22 22:13:00

Twilight6 发表于 2020-7-22 08:58
试试这段代码就知道是不是同一内存了:




好的,感谢!
页: [1]
查看完整版本: 关于闭包的内存问题