Шаг 67.
Python: тонкости программирования.
Классы и ООП. Клонирование объектов. Создание мелких копий

    На этом шаге мы рассмотрим создание мелких копий.

    В приведенном ниже примере мы создадим новый вложенный список и затем мелко его скопируем при помощи фабричной функции 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.

    На следующем шаге мы рассмотрим создание глубоких копий.




Предыдущий шаг Содержание Следующий шаг