На этом шаге мы рассмотрим создание мелких копий.
В приведенном ниже примере мы создадим новый вложенный список и затем мелко его скопируем при помощи фабричной функции list():
>>> xs = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] >>> ys = list(xs) # Сделать мелкую копию
Это означает, что список ys теперь будет новым и независимым объектом с тем же самым содержимым, что и список xs. Это можно проверить, проинспектировав оба объекта:
>>> xs [[1, 2, 3], [4, 5, 6], [7, 8, 9]] >>> ys [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Чтобы подтвердить, что список ys действительно независим от оригинала, давайте разработаем маленький эксперимент. Можно попробовать добавить новый подсписок в оригинал (xs) и затем убедиться, что эта модификация не затронула копию (ys):
>>> xs.append(['новый подсписок']) >>> xs [[1, 2, 3], [4, 5, 6], [7, 8, 9], ['новый подсписок']] >>> ys [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Как видите, эффект был ожидаем. С изменением скопированного списка на "поверхностном" уровне никаких проблем не возникло.
Однако поскольку мы создали лишь мелкую копию оригинального списка, список ys по-прежнему содержит ссылки на оригинальные дочерние объекты, хранящиеся в xs.
Эти дочерние элементы не были скопированы. Все свелось к тому, что в скопированном списке на них снова содержатся ссылки.
Поэтому, когда вы модифицируете один из дочерних объектов в списке xs, эта модификация также будет отражена в списке ys - таким образом, оба списка совместно используют одинаковые дочерние объекты. Эта копия представляет собой всего лишь мелкую копию с одним уровнем в глубину:
>>> xs[1][0] = 'X' >>> xs [[1, 2, 3], ['X', 5, 6], [7, 8, 9], ['новый подсписок']] >>> ys [[1, 2, 3], ['X', 5, 6], [7, 8, 9]]
В примере выше мы (казалось бы) изменили только список xs. Но оказывается, что в индексе 1 списков xs и ys были изменены оба подсписка. Опять-таки, это произошло, потому что мы создали всего-навсего мелкую копию оригинального списка.
Если бы на первом шаге мы создали глубокую копию списка xs, то оба объекта были бы полностью независимы. В этом и заключается практическая разница между мелкими и глубокими копиями объектов.
Теперь вы знаете, как создавать мелкие копии некоторых встроенных классов коллекций, и знаете разницу между мелким и глубоким копированием. Вопросы, ответы на которые мы по-прежнему хотим получить, следующие:
Ответы на эти вопросы лежат в модуле copy стандартной библиотеки Python. Этот модуль обеспечивает простой интерфейс для создания мелких и глубоких копий произвольных объектов Python.
На следующем шаге мы рассмотрим создание глубоких копий.