Удаление переменной из памяти Python

Удаление переменной из памяти Python


У меня технический вопрос. Пишу на Python. Две переменные задаются таким образом:

a = 5
b = a
del a
print(b)

Программа выводит:

5

Почему программа выводит 5, а не None? Ведь две переменные указывают на одну область памяти и мы ее удаляем, получается переменная b должна быть None. Почему она все-равно равняется 5? Очищается ли эта область памяти при вызове del или она переписывается в другое место, но как тогда ее очистить?





Когда мы инициализируем переменную a = 5 то в памяти создаётся объект типа int со значением 5, и переменная a начинает ссылаться на этот объект (хотя если в памяти уже был объект int=5 то в целях экономии памяти новый объект может и не создаться)

Теперь b = a переменная b начинает ссылаться на тот же объект, что и a. И тут важно, что не происходит копирование переменной a, а получается копирование ссылки на объект, которым является число 5. В памяти в этот момент существует один объект — число 5, и обе переменные ссылаются на него (а может и еще другие переменные на него ссылаются, но это уже оптимизации самого Python).

А вот сам del a удаляет непосредственно переменную a, но не объект, на который она ссылается. Поскольку на объект 5 по-прежнему ссылается переменная b, объект не удаляется, и память не очищается.

И теперь самое очевидное print(b) отработает поскольку переменная b всё ещё указывает на объект 5, ведь del a просто удалил переменную a, но не int 5 в памяти.

А вот непосредственно из памяти объекты удаляет сборщик мусора. В Python для удобства и автоматизации/оптимизации этот самый сборщик сам находит для очистки объекты, которые больше не имеют ссылок. В данном случае объект 5 остаётся в памяти до тех пор, пока существует хотя бы одна ссылка на него. А вот когда все ссылки на объект будут удалены (например, если мы также сделаем del b или присвоим ей другое значение), объект станет "доступен для удаления", и сборщик мусора его выгрузит из памяти.

Так что если хотим полностью удалить объект из памяти, то придётся найти и удалить все ссылки на этот объект. В данном случае:

a = 5
b = a
del a
del b  

Теперь нет ссылок на объект 5 и int 5 будет выгружен из памяти сборщиком мусора при следующей его ревизии объектов в памяти.


К слову, небольшие целые числа в диапазоне от -5 до 256 кэшируются интерпретатором и хранятся в специальном массиве, и они никогда не удаляются, поскольку часто используются.

Забавный пример:

>>> a = 10
>>> b = 300
>>> a is 10
True
>>> b is 300
False

Числа вне диапазона -5, 256 интерпретатор тоже будет пытаться оптимизировать, но только если они находятся в одной строке (или одном файле). В командной строке интерпретатора так не работает:

>>> d = 400
>>> d is 400
False

а так будет:

a = 5
b = 300

print(a is 5)  # True
print(b is 300) # True

Так же в Python есть интернирование строк — это своего рода оптимизация, которая позволяет уменьшить количество строковых объектов в памяти по средству кэширования некоторых строк (происходит автоматически для коротких строк).

a = "hello world!"
b = "hello world!"
print(a is b)  # True

a = "hello my litl world is the good job, " * 300
v = "hello my litl world is the good job, " * 300
print(a is v)  # False

z = f"hello {b}" 
x = f"hello {b}" 
print(z is x)  # False

import sys
a = sys.intern(a)
v = sys.intern(v)
print(a is v)  # Теперь True, строки интернированы вручную

z = sys.intern(z)
x = sys.intern(x)
print(z is x)  # Тоже True

В общем, del не удаляет объект, а просто удаляет переменную и её копию ссылки на объект. Надеюсь понятно изложи







Report Page