Короткий ответ
Поверхностная копия создаёт новый внешний объект, но сохраняет те же ссылки на вложенные изменяемые объекты, поэтому изменение вложенного объекта затронет и оригинал, и копию; глубокое копирование рекурсивно копирует все вложенные объекты, создавая полностью независимую структуру.
Как это работает подробнее
copy.copy(obj) (или list(obj), dict(obj), срез obj[:]) создаёт новый контейнер верхнего уровня, но копирует в него те же самые ссылки на вложенные объекты, а не их содержимое. copy.deepcopy(obj) рекурсивно обходит структуру и создаёт новые копии на каждом уровне вложенности, используя memo-словарь, чтобы корректно обрабатывать циклические ссылки без бесконечной рекурсии.
Пример кода
example.py
import copy
original = {"items": [1, 2, 3], "meta": {"owner": "team-a"}}
shallow = copy.copy(original)
shallow["items"].append(4)
print(original["items"]) # [1, 2, 3, 4] — изменилось и в оригинале!
deep = copy.deepcopy(original)
deep["items"].append(99)
print(original["items"]) # [1, 2, 3, 4] — оригинал не затронут deepcopyЧто использовать на практике
- Практика. Для "плоских" структур (список чисел или строк) поверхностная копия и глубокая дают одинаковый практический результат, так как элементы неизменяемы. Для структур с вложенными list/dict/объектами выбор критичен: если нужна полностью независимая копия для безопасной модификации — нужен deepcopy, который дороже по времени и памяти, поэтому его не стоит использовать там, где достаточно поверхностной копии.
Подводные камни
- Риски. Используют
list(nested_list)илиdict.copy(), ожидая полностью независимую структуру, и затем случайно изменяют вложенные списки/словари как в оригинале, так и в "копии". Также применяютdeepcopyбез необходимости в горячем пути, что создаёт заметные накладные расходы на больших структурах.