Удаление переменной из памяти 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 не удаляет объект, а просто удаляет переменную и её копию ссылки на объект. Надеюсь понятно изложи