Присваивание создаёт связь, а не дубликат содержимого
Имя позволяет обратиться к объекту. Когда другому имени присваивают уже существующий список, оба имени могут указывать на один и тот же объект. Само присваивание не обещает независимого списка с отдельно сохранёнными элементами. Представим список для вымышленного склада: чай и рис. Имена исходный и рабочий связаны с этим одним списком. Если через рабочее имя добавить соль, изменится сам объект. Обращение через исходное имя тоже покажет соль, потому что оно по-прежнему ведёт к тому же объекту.
Изменение объекта отличается от новой привязки имени
Теперь другой случай: рабочему имени назначили новый список, содержащий только кофе. Это не операция добавления в прежний список. Рабочее имя стало ссылаться на другой объект, а исходное осталось связано с прежним. На бумажной схеме разница видна сразу. При добавлении элемента меняется прямоугольник, изображающий список. При присваивании нового списка меняется стрелка от имени. Смешение этих двух действий часто приводит к неверному ожиданию, будто любое использование второго имени либо всегда меняет первое, либо никогда на него не влияет.
Копирование тоже имеет границы
Для плоского списка можно создать отдельную поверхностную копию. Тогда добавление нового элемента в саму копию не добавляет его в исходный список: это уже два отдельных внешних объекта. Но слово копия требует уточнения, если внутри находятся другие изменяемые объекты. Поверхностное копирование создаёт новый внешний контейнер, сохраняя ссылки на вложенные элементы. Поэтому вложенный список может оставаться общим. Глубокое копирование решает другую задачу, но его не стоит применять автоматически ко всем данным. Для начала полезно точно понять, какие объекты должны быть независимыми, а какие намеренно используются совместно.
Попробуйте на практике
Изобразите связи имён и списков на бумаге. Интерпретатор Python, установка программ и работа с реальными складскими данными не нужны.
- Нарисуйте один прямоугольник со словами чай и рис. Проведите к нему две стрелки от имён исходный и рабочий. Подпишите, сколько объектов изображено.
- Добавьте соль внутрь этого прямоугольника. Запишите, что будет видно через каждое имя, не рисуя второй список задним числом.
- Нарисуйте новый прямоугольник с кофе и перенаправьте к нему только стрелку рабочего имени. Отметьте, какие элементы теперь доступны через исходное имя.
- Создайте отдельный рисунок двух внешних списков после поверхностного копирования. Если оба содержат ссылку на один вложенный список, покажите этот общий внутренний объект отдельным прямоугольником.
Как проверить результат. После первого добавления оба имени должны вести к чаю, рису и соли. После перенаправления рабочего имени исходный список сохраняется. На схеме поверхностной копии должны различаться два внешних контейнера и общий вложенный объект, если он задан условием.
Частые вопросы
Списки с одинаковыми элементами обязательно являются одним объектом?
Нет. Одинаковое содержимое не доказывает общность объекта. Важно, как списки создавались и какие связи между ними существуют.
Почему нельзя всегда использовать глубокую копию?
Иногда совместное использование объектов задумано специально, а независимое копирование избыточно. Выбор зависит от структуры данных и требуемого поведения, а не от стремления добавить копирование везде.
Эта проблема относится только к двум коротким именам?
Нет. Те же вопросы возникают при передаче изменяемых объектов между частями программы. Схема связей помогает рассуждать о поведении независимо от длины имён.
Самостоятельный разбор темы. Содержание конкретной обучающей программы здесь не представлено.