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


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

Перечень интерфейсных функций:

copy.copy(x)

Возвратить поверхностную копию x.

copy.deepcopy(x[, memo])

Возвратить глубокую копию x.

exception copy.error

Вызывается для модуля определяющего ошибки.

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

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

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

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

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

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

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

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

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

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

См.также

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