Почему IPython управляет памятью иначе, чем CPython, когда я удаляю список? - PullRequest
5 голосов
/ 24 сентября 2019

Недавно я узнал, что когда вы удаляете список в 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

Как я могу объяснить причину, по которой эти списки имеют одинаковый идентификатор, я не могу понять, почему это разница между ipython и python.

Посмотрите на реализацию List listobject.c .

Как мы видим, существует массивссылок под названием free_list.значениями массива которых является список уничтоженных объектов, а количество numfree для индексации массива.мы видим, что если удалено более 80 списков, следующий не будет сохранен в массиве.поэтому из этой строки мы можем сказать, что мое утверждение всегда может быть верным для любого нового интерпретатора Python.

, но я до сих пор не могу найти причину для ipython для такой работы

1 Ответ

4 голосов
/ 25 сентября 2019

Во-первых, id() не имеет ничего общего с общим управлением памятью в языке Python.Однако в CPython (отсюда и IPython REPL) он имеет непосредственное соответствие с необработанными ячейками памяти.В некоторых комментариях указывалось, что этот вопрос не обязательно имеет смысл в абстрактном виде, но ограничен IPython и стандартным CPLthon REPL, который кажется применимым.

Все, что происходит, заключается в том, что при обработке вашего блока ячеек IPythonСреда создает несколько дополнительных объектов (в том числе список объектов) за кулисами.Поскольку исходное пространство памяти из l занято для некоторых списков, которые IPython создал за кулисами, распределитель CPython находит новый блок памяти для g.

Для некоторых свидетельств дополнительных объектоврассмотрим следующий эксперимент, запущенный как на CPython, так и на IPython, который анализирует сборщик мусора.

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
...