Предполагается, что вы уже умеете писать простые программы на Python и знаете базовый синтаксис (if, for, функции, списки). Здесь мы разбираем не как пользоваться языком, а почему он работает именно так.

Попробуйте угадать, что выведет этот код.

numbers = [1, 2, 3]
other = numbers

del numbers

print(other)

Многие ожидают, что программа завершится с ошибкой.

Ведь мы только что удалили список.

Однако Python спокойно выводит:

[1, 2, 3]

Получается странная ситуация.

Мы удалили список.

Но он почему-то продолжает существовать.

Почему?


Чтобы ответить на этот вопрос, давайте вспомним одну из первых статей этой серии.

Когда мы пишем:

numbers = [1, 2, 3]

переменная не хранит список внутри себя.

Создаётся объект списка.

А имя numbers начинает ссылаться на него.

Позже выполняется ещё одна строка:

other = numbers

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

Схематично это выглядит так:

numbers  ─┐


      [1, 2, 3]


other ────┘

Теперь выполняется самая интересная строка.

del numbers

Что происходит?

Многие представляют себе, что Python уничтожает объект.

Но это не так.

Оператор del вообще не работает с объектами.

Он работает только с именами.

После выполнения этой строки схема становится такой:

      [1, 2, 3]


other ────┘

Имя numbers исчезло.

Но объект остался.

Потому что на него по-прежнему ссылается имя other.

Именно поэтому следующая строка:

print(other)

совершенно спокойно выводит содержимое списка.


Попробуем другой пример.

numbers = [1, 2, 3]

del numbers

print(numbers)

Теперь программа действительно завершится ошибкой.

Но важно понимать причину.

Ошибка возникает не потому, что Python не смог найти объект.

Ошибка возникает потому, что больше не существует имени numbers.

Когда Python пытается выполнить:

print(numbers)

он ищет имя numbers.

Но такого имени уже нет.

Поэтому возникает:

NameError

Обратите внимание.

Ошибка говорит именно об имени.

Не об объекте.


Можно сказать, что del разрывает связь между именем и объектом.

Сам объект при этом может продолжать существовать.

Или не продолжать.

Это зависит только от одного вопроса.

Есть ли ещё хотя бы одно имя, которое на него ссылается?


Посмотрим ещё один пример.

numbers = [1, 2, 3]

other = numbers

third = numbers

del numbers
del other

print(third)

Что произойдёт?

Ответ уже должен быть очевиден.

Список продолжит существовать.

Потому что имя third всё ещё ссылается на него.

Можно удалить хоть десять имён.

Пока остаётся хотя бы одно, объект никуда не исчезает.


Теперь возникает очень интересный вопрос.

А что произойдёт, если исчезнет последнее имя?

Например:

numbers = [1, 2, 3]

del numbers

Казалось бы, теперь на объект больше никто не ссылается.

Означает ли это, что Python немедленно удалит его из памяти?

Или существуют какие-то другие правила?

Именно этот вопрос мы разберём в следующей статье.