copy — Операции поверхностного и глубокого копирования

Источник: Lib/copy.py


Операторы присваивания в Python не копируют объекты, они создают привязку между целью и объектом. Для коллекций, которые являются изменяемыми или содержат изменяемые элементы, иногда требуется копирование, чтобы можно было изменить одну копию, не изменяя другую. Этот модуль предоставляет общие операции поверхностного и глубокого копирования (объясняется ниже).

Краткое описание интерфейса:

copy.copy(obj)

Возвращает неглубокую копию obj.

copy.deepcopy(obj[, memo])

Возвращает глубокую копию obj.

copy.replace(obj, /, **changes)

Создает новый объект того же типа, что и obj, заменяя поля значениями из changes.

Added in version 3.13.

exception copy.Error

Возникает при ошибках, специфичных для модуля.

Разница между поверхностным и глубоким копированием актуальна только для составных объектов (объектов, содержащих другие объекты, например, списки или экземпляры классов):

  • При глубокой копии создается новый составной объект, а затем (насколько это возможно) в него вставляются ссылки на объекты, имеющиеся в оригинале.

  • При глубоком копировании создается новый составной объект, а затем в него рекурсивно вставляются копии объектов, содержащихся в оригинале.

При выполнении операций глубокого копирования часто возникают две проблемы, которых нет при выполнении операций поверхностного копирования:

  • Рекурсивные объекты (составные объекты, которые прямо или косвенно содержат ссылку на себя) могут вызвать рекурсивный цикл.

  • Поскольку глубокое копирование копирует все, оно может скопировать слишком много, например данные, предназначенные для обмена между копиями.

Функция deepcopy() позволяет избежать этих проблем:

  • ведение словаря memo объектов, уже скопированных во время текущего прохода копирования; и

  • позволяет пользовательским классам переопределять операцию копирования или набор копируемых компонентов.

Этот модуль не копирует такие типы, как модуль, метод, трассировка стека, кадр стека, файл, сокет, окно или другие подобные типы. Он «копирует» функции и классы (поверхностно и глубоко), возвращая исходный объект неизменным; это совместимо с тем, как они обрабатываются модулем pickle.

Неглубокие копии словарей можно сделать с помощью dict.copy(), а списков - назначив фрагмент всего списка, например, copied_list = original_list[:].

Классы могут использовать те же интерфейсы для управления копированием, что и для управления травлением. Информацию об этих методах см. в описании модуля pickle. Фактически, модуль copy использует зарегистрированные функции pickle из модуля copyreg.

Для того чтобы класс мог определить собственную реализацию копирования, он может определить специальные методы __copy__() и __deepcopy__().

object.__copy__(self)

Вызывается для реализации операции неглубокого копирования; дополнительные аргументы не передаются.

object.__deepcopy__(self, memo)

Вызывается для реализации операции глубокого копирования; ей передается один аргумент - словарь memo. Если реализации __deepcopy__ необходимо сделать глубокую копию компонента, она должна вызвать функцию deepcopy() с компонентом в качестве первого аргумента и словарем memo в качестве второго аргумента. Словарь memo следует рассматривать как непрозрачный объект.

Функция copy.replace() является более ограниченной, чем copy() и deepcopy(), и поддерживает только именованные кортежи, созданные namedtuple(), dataclasses и другими классами, определяющими метод __replace__().

object.__replace__(self, /, **changes)

Этот метод должен создать новый объект того же типа, заменив поля значениями из changes.

См.также

Модуль pickle

Обсуждение специальных методов, используемых для поддержки поиска и восстановления состояния объекта.