python - 为什么在删除列表时 IPython 管理内存的方式与 CPython 不同?

标签 python python-3.x list ipython python-internals

我最近了解到,当你在 Python 中删除一个列表时,这个列表的引用会保存在一个数组中,并在你初始化一个新列表时弹出。

我在我的常规解释器中运行了这个:

l = [1,2,3]
l_id = id(l)
del l
g = [1,2,3]
id(g) == l_id # True

正如预期的那样,我得到了正确的结果。

我在我的 IPython 解释器上尝试了同样的事情,却得到了 False。为什么会这样?好点了吗?

Python版本:v3.7.0:1bf9cc5093

Ipython 版本:7.5.0

更新

它也发生在不同的列表中:

l = [1,2,3]
l_id = id(l)
del l
g = [1,2,3,4,5,6,7,8]
id(g) == l_id # True

而且它总是发生,他们得到相同的引用并不是随机的事情

更新2

我知道为什么会这样,我只是想知道为什么它只发生在纯 python 解释器上而不是在我的 ipython 上,以及这些方法中哪一种更适合内存管理

更新 3

因为我可以解释这些列表具有相同 ID 的原因,所以我不明白为什么 ipython 和 Python 之间存在差异。

看List listobject.c的实现.

正如我们所见,有一个引用数组,称为free_list。其中数组的值是被销毁的列表对象,数组索引的计数numfree。我们可以看到,如果删除了超过 80 个列表,则下一个列表不会保存在数组中。所以从这些行我们可以说我的陈述对于任何新的 python 解释器都是正确的。

但我仍然找不到让 ipython 像这样工作的原因

最佳答案

首先,id() 与 Python 语言中的一般内存管理没有任何关系。但是,在 CPython(因此是 IPython REPL)中,它与原始内存位置具有一对一的对应关系。一些评论指出,这个问题在抽象上不一定有意义,但仅限于 IPython 和标准 CPython REPL 似乎适用。

所有发生的事情是,在处理您的单元格 block 时,IPython 环境在幕后创建了一些额外的对象(包括列表对象)。由于 l 的原始内存空间被 IPython 在幕后创建的一些列表占用,因此 CPython 分配器为 g 找到了一个新的内存块。

要获得额外对象的一些证据,请考虑以下在 CPython 和 IPython 中运行的内省(introspection)垃圾收集器的实验。

from gc import get_objects
orig = set(map(id, get_objects()))
l = [1,2,3]
l_id = id(l)
del l
g = [1,2,3]
final = set(map(id, get_objects()))
len(orig.symmetric_difference(final))  # 2 in CPython, 6-40+ in IPython

关于python - 为什么在删除列表时 IPython 管理内存的方式与 CPython 不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58087537/

相关文章:

Python 停止且没有错误

python - 匹配不以已知字符串列表结尾的字符串

python - Python Django 的多线程

Python:如何在单个 URL 的 2 个修订版之间创建差异/补丁文件?

python - 如何从 QDialog 访问 QMainWindow 中的小部件

python - 如何使用 eyed3 模块从 Mp3 中删除现有的专辑封面图像

python - 使用多处理模块时如何提高 CPU 利用率?

python - 单个列表中可能的列表组合

jquery - 带有 block 嵌套列表的内联列表用于菜单

python - 如何将较小列表中的数字连续添加到较大的python列表中