Ответ
В Python copy() и deepcopy() служат для создания копий объектов, но работают на разной глубине, что критично для изменяемых (mutable) объектов, содержащих другие изменяемые объекты (например, список списков).
1. Поверхностное копирование (copy() или copy.copy()):
Создает новый составной объект (например, новый список), но затем вставляет в него ссылки на те же вложенные объекты, что и в оригинале.
import copy
original = [1, 2, [3, 4]]
shallow_copy = original.copy() # или copy.copy(original)
# Изменение элемента верхнего уровня затрагивает только копию
shallow_copy[0] = 99
print("Original:", original) # [1, 2, [3, 4]]
print("Shallow copy:", shallow_copy) # [99, 2, [3, 4]]
# Изменение ВЛОЖЕННОГО изменяемого объекта затрагивает и оригинал!
shallow_copy[2][0] = 88
print("nAfter modifying nested list:")
print("Original:", original) # [1, 2, [88, 4]] <- ИЗМЕНИЛСЯ!
print("Shallow copy:", shallow_copy) # [99, 2, [88, 4]]
2. Глубокое копирование (deepcopy()):
Создает новый составной объект, а затем рекурсивно создает копии всех вложенных объектов. В результате получается полностью независимая копия.
import copy
original = [1, 2, [3, 4]]
deep_copy = copy.deepcopy(original)
# Изменение вложенного объекта теперь безопасно
deep_copy[2][0] = 88
print("Original:", original) # [1, 2, [3, 4]] <- НЕ изменился
print("Deep copy:", deep_copy) # [1, 2, [88, 4]]
Когда что использовать:
copy(): Когда у вас плоская структура (список чисел, строк) или вы намеренно хотите, чтобы вложенные объекты разделялись (например, для экономии памяти, если они неизменяемы).deepcopy(): Когда у вас сложная, вложенная структура (словарь списков, список словарей, пользовательские объекты с атрибутами-списками) и вам нужна полная, независимая копия. Учтите,deepcopy()может быть значительно медленнее и требовательнее к памяти для больших структур.
Важно: Для неизменяемых (immutable) объектов, таких как кортежи, строки или числа, разницы между copy() и deepcopy() нет, так как их нельзя изменить.
Ответ 18+ 🔞
Э, слушай, а вот эта тема с копированием в питоне — это просто ёперный театр какой-то. Люди думают, что скопировал список — и всё, свободен, а потом у них программа ведёт себя как хитрая жопа, и они охуевают, не понимая, откуда ноги растут.
Короче, есть два главных героя: copy() и deepcopy(). Разница между ними — это как между «чуть-чуть» и «полностью». И если её не понимать, будет вам хиросима и нагасаки в одном флаконе.
1. Поверхностное копирование (copy() или copy.copy())
Это как взять свою старую куртку и надеть её на нового чувака. Куртка-то новая, а карманы — те же самые, общие. Создаётся новый объект верхнего уровня, но внутрь засовываются ссылки на те же самые вложенные штуки, что и в оригинале.
import copy
original = [1, 2, [3, 4]]
shallow_copy = original.copy() # или copy.copy(original)
# Меняем что-то на поверхности — всё ок, копия отдельно
shallow_copy[0] = 99
print("Original:", original) # [1, 2, [3, 4]]
print("Shallow copy:", shallow_copy) # [99, 2, [3, 4]]
# А вот сейчас — внимание, хуй с горы! Тыкаемся во вложенный список
shallow_copy[2][0] = 88
print("nПосле изменения вложенного списка:")
print("Original:", original) # [1, 2, [88, 4]] <- Бля! И оригинал поменялся!
print("Shallow copy:", shallow_copy) # [99, 2, [88, 4]]
Видишь? Вложенный список [3, 4] — это один и тот же объект в памяти для обоих. Поменял в копии — ебааать, и оригинал поплыл. Доверия к такому копированию — ноль ебать.
2. Глубокое копирование (deepcopy())
А вот это уже серьёзно. deepcopy() идёт и рекурсивно копирует всё до самого дна, создавая полностью независимый клон. Это как сделать ксерокс не только страницы, но и всех вложенных в файл бумажек.
import copy
original = [1, 2, [3, 4]]
deep_copy = copy.deepcopy(original)
# Теперь можно долбить вложенные структуры без страха
deep_copy[2][0] = 88
print("Original:", original) # [1, 2, [3, 4]] <- Спокойно, не шелохнулся
print("Deep copy:", deep_copy) # [1, 2, [88, 4]]
Вот теперь всё чисто. Оригинал и копия живут отдельной жизнью, как соседи по подъезду, которые друг друга ненавидят.
Так когда что юзать?
copy(): Когда у тебя структура простая, плоская (список из чисел, строк) или когда тебе нарочно нужно, чтобы вложенные объекты были общими (например, они неизменяемые и память жалко). Но будь готов, что если там что-то mutable затесалось — пиши пропало.deepcopy(): Когда у тебя структура сложная, как мозги после пятницы: список списков, словарь списков, свои классы с кучей атрибутов-списков. Нужна полная независимость — бериdeepcopy. Да, он жрёт память и может быть медленным для овердохуища больших структур, но зато спать спокойно.
Важный нюанс: Для неизменяемых объектов (кортежи, строки, числа) похуй, какую копию делать. Их всё равно не изменишь, так что разницы нет. Но как только появляется что-то изменяемое внутри — вот тут и начинается настоящая магия, а точнее, пиздец, если невнимательный.