"Олег Бройтман. Python - основные концепции " - читать интересную книгу автора

экземпляр класса с деструктором), и память объекта освобождается.
Такой механизм называется "синхронной сборкой мусора со счетчиком
ссылок". Помимо него, в Питоне есть асинхронный сборщик мусора, достоинство
которого в том, что он умеет распознавать циклические ссылки и очищать
объекты, на которые нет других ссылок (не из цикла). (Пример циклических
ссылок: l=[]; l.append(l))
Рассмотрим поподробнее питоновские ссылки. Создадим список и присвоим
его (на самом деле присвоим ссылку на него) в переменную a: a = [21, 12,
"str"]. Теперь присвоим ссылку из a в переменную b: a = b. Изменим список,
на который ссылается a, скажем, добавим в него содержимое другого списка: a
+= [2000]. На какой список ссылается переменная b? На тот же, что и a - на
список из 4 элементов. Происходит это потому, что b все еще хранит ссылку на
тот же список, что и a. А теперь присвоим в a новый список: a = [12, 21].
Что теперь будет в b? А все тот же список из 4 элементов. Присваивание в a
разорвало связь между a и b. В переменной a теперь ссылка на новый список, а
в переменной b все та же ссылка на тот же список.
Если a - переменная, хранящая ссылку на список, и присваивание b = a
копирует только ссылку на тот же список, то можно ли скопировать сам список?
Короткий ответ - да, можно. Но не все так просто. Ведь и сам список хранит
не объекты, а ссылки на объекты. Должны ли копироваться эти ссылки или
должны быть продублированы и сами объекты? Питон дает два ответа на этот
вопрос: можно сделать и так, и эдак. Первый вариант копирования называется
"поверхностным", второй - "глубоким" копированием. Глубокое копирование
учитывает циклические ссылки. Классы, написанные программистом, могут
определять методы, участвующие в копировании, тем самым "помогая" процессу
копирования, для того чтобы не включать в копирование лишней информации.
Манипуляции с неизменяемыми объектами осуществляются путем создания
новых объектов. Например, если в строке надо заменить символ, исходная
строка разбивается на две подстроки, и из них (плюс новый символ) создается
новая строка. Если в переменной a ссылка на цело число, то в результате
операции a += 1 в a окажется ссылка на новое число.