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

В языке Python оператор присваивания (=) не создает копию объекта. Он лишь создает новую ссылку на тот же самый кусок памяти. Если объект является мутабельным (изменяемым) списком или словарем, изменение одной переменной приведет к изменению другой. Модуль copy решает эту проблему.

import copy

В чем проблема?

Если мы сделаем так:

a = [[1, 2], [3, 4]]
b = a

b[0][0] = 99
print(a) # Выведет [[99, 2], [3, 4]] — оригинал тоже пострадал!

Поверхностное копирование (Shallow Copy)

Функция copy.copy(x) создает новый контейнер (новый "внешний" список), но заполняет его ССЫЛКАМИ на старые дочерние элементы. Для простых списков этого достаточно, но для вложенных словарей и матриц — нет.

import copy

a = [[1, 2], [3, 4]]
b = copy.copy(a)       # Эквивалент b = a.copy() или b = list(a)

b.append([5, 6])       # Безопасно, добавляется только в 'b'
b[0][0] = 99           # НЕБЕЗОПАСНО: внутренние списки по-прежнему общие!

print(a[0][0])         # Выведет 99

Глубокое копирование (Deep Copy)

Функция copy.deepcopy(x) рекурсивно копирует не только родительский список, но и все вложенные в него массивы, словари и объекты (до самого дна). Это создает полностью независимого клона.

import copy

a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)

b[0][0] = 99           # Теперь 'b' независима

print(a)               # Оригинал: [[1, 2], [3, 4]]
print(b)               # Измененная: [[99, 2], [3, 4]]

Важно: deepcopy работает значительно медленнее и потребляет в два раза больше памяти. Используйте его только тогда, когда у вас действительно есть вложенные изменяемые списки/словари/классы.


Полный справочник API (API Reference)

Основные функции

Функция Описание
copy.copy(x) Создает поверхностную (shallow) копию объекта x.
copy.deepcopy(x) Создает независимую, полностью рекурсивную (deep) копию объекта x. Спасает круговые (ссылающиеся сами на себя) ссылки от зацикливания.

Магические методы

Классы могут сами управлять тем, как именно их должны "копировать", реализуя эти методы.

Магический Метод Описание
__copy__(self) Вызывается интерпретатором при использовании copy.copy().
__deepcopy__(self, memo) Вызывается при использовании copy.deepcopy(). memo — это словарь, защищающий глубокое копирование от бесконечной рекурсии.