a = 'aaaa'
print(id(a))
del a
b = 'aaaa'
print(id(b))
# 为什么两次打印出的内存地址是一样的,看起来 del a 之后'aaaa'并没有被垃圾回收,引用计数不是具有实时性吗?
# 如果是在交互式 ipython 下,两次打印倒是不一样的。emm 看了 py 文件的运行机制也没有搞清楚这个问题,可能是这个运行机制看的不是很透彻,求大佬指点。
1
xcstream 2020-04-16 16:07:34 +08:00
‘aaaa’是常量了 固定住内存地址
|
2
xcstream 2020-04-16 16:08:47 +08:00
ipython 在启动后没有'aaaa' 需要生成一个新的
|
3
TanLeDeDaNong 2020-04-16 16:18:10 +08:00
具体可以查下 python 的垃圾回收机制,有个问题思考一下:1. python 是不是 del 之后马上垃圾回收, 我理解的并不是 ,是有延时的。2. 为什么命令行会回收,你可以尝试 sleep 一下。
|
4
xiri 2020-04-16 16:18:23 +08:00
发生字符串驻留了,Cpython 在编译优化时会尝试重复使用已经存在的不可变对象而不是每次都创建一个新对象(当然,要满足一定的条件)
|
5
iamdaguduizhang OP @TanLeDeDaNong emm 1.垃圾回收不是一个 del 那么简单诶。2.和 sleep 没有关系的。依然感谢
|
6
iamdaguduizhang OP @xiri 你是说类似于小整数对象池的那个嘛?
|
7
iamdaguduizhang OP @xcstream 固定住内存地址? 我在 del 前打印了引用计数发现是 4 诶,
|
8
chenstack 2020-04-16 16:48:28 +08:00
的确是有字符串驻留了,但即使没有驻留,这种情况下 id 也是一样的
a = object() print(id(a)) del a b = object() print(id(b)) |
9
xiri 2020-04-16 16:55:35 +08:00
@iamdaguduizhang 你可以打印一下"aaaa"的引用计数,a 变量被删掉了,但是"aaaa"这个常量没有哦
import sys a = "aaaa" print(sys.getrefcount("aaaa")) del a print(sys.getrefcount("aaaa")) b = "aaaa" c = "aaaa" print(sys.getrefcount("aaaa")) 你可以试一下上面的代码,输出是 4 、3 、5,del a 之后"aaaa"的引用减了 1,但是并没有被删掉,如果打印一下 a,b,c 的 id 会发现都是一样的,他们都指向内存中同一个字符串对象。可以看一下下面这个说明,这是 Cpython 的一种编译优化 https://github.com/leisurelicht/wtfpython-cn#-strings-can-be-tricky-sometimes%E5%BE%AE%E5%A6%99%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2- |
10
pompeii 2020-04-16 16:58:29 +08:00
>>> import gc
>>> a = 'aaa' >>> id(a) 77627920L >>> del a >>> gc.collect() 0 >>> b = 'aaa' >>> id(b) 77629040L 所以垃圾回收应该不是实时的 |
11
iamdaguduizhang OP @xiri 恩恩,感谢。我明白你说的字符串驻留了。 看起来现在我的疑问变成了第一次打印引用计数的值不是 ipython 里的 1 ? 所以 del 之后还是字符串没有被回收,然后就出现了字符串驻留诶
|
12
iamdaguduizhang OP @pompeii emm,感觉不能通过 交互式有时间间隔来证明垃圾回收不是实时的诶。
|
13
iamdaguduizhang OP @chenstack 感谢~
|