Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как использовать copy в Python
Модуль copy в Python предоставляет функции для создания копий объектов. Это критически важно для понимания, так как многие разработчики путают поверхностное и глубокое копирование, что приводит к багам. Разберу детально.
Основная проблема: ссылки vs копии
# ❌ Это не копирование, а присваивание ссылки
original = [1, 2, [3, 4]]
shallow = original # Обе переменные указывают на ОДИН объект!
shallow[0] = 999
print(original) # [999, 2, [3, 4]] — оригинал изменился!
1. Shallow Copy (Поверхностное копирование)
Копирует сам объект, но не копирует вложенные объекты:
import copy
original = [1, 2, [3, 4]]
shallow = copy.copy(original)
# Изменение элемента первого уровня
shallow[0] = 999
print(original) # [1, 2, [3, 4]] — оригинал не изменился ✓
# Но вложенный список общий!
shallow[2].append(5)
print(original) # [1, 2, [3, 4, 5]] — оригинал изменился ✗
2. Deep Copy (Глубокое копирование)
Рекурсивно копирует всё, включая вложенные объекты:
import copy
original = [1, 2, [3, 4]]
deep = copy.deepcopy(original)
# Изменение любого уровня не влияет на оригинал
deep[2].append(5)
print(original) # [1, 2, [3, 4]] — оригинал не изменился ✓
print(deep) # [1, 2, [3, 4, 5]]
3. Практические примеры
С словарями:
original_dict = {
"name": "Alice",
"scores": [10, 20, 30]
}
# Shallow copy
shallow = copy.copy(original_dict)
shallow["scores"].append(40)
print(original_dict) # scores изменился — [10, 20, 30, 40]
# Deep copy
deep = copy.deepcopy(original_dict)
deep["scores"].append(50)
print(original_dict) # scores не изменился — [10, 20, 30, 40]
С пользовательскими классами:
class User:
def __init__(self, name, skills):
self.name = name
self.skills = skills
user1 = User("Bob", ["Python", "SQL"])
# Shallow copy
user2 = copy.copy(user1)
user2.skills.append("Django") # Изменяется список user1!
# Deep copy
user3 = copy.deepcopy(user1)
user3.skills.append("FastAPI") # user1 не затронут ✓
4. Альтернативные способы копирования
Для списков:
original = [1, 2, 3]
# Способ 1: срез
copy1 = original[:] # shallow copy
# Способ 2: конструктор
copy2 = list(original) # shallow copy
# Способ 3: copy.copy()
copy3 = copy.copy(original) # shallow copy
Для словарей:
original = {"a": 1, "b": [2, 3]}
# Способ 1: распаковка
copy1 = {**original} # shallow copy
# Способ 2: конструктор
copy2 = dict(original) # shallow copy
# Способ 3: copy.copy()
copy3 = copy.copy(original) # shallow copy
5. Кастомное копирование в классах
Если класс имеет сложную логику, переопредели методы копирования:
class DataModel:
def __init__(self, data):
self.data = data
self._cache = {} # Не копируем кэш
def __copy__(self):
new_obj = self.__class__(self.data[:])
return new_obj
def __deepcopy__(self, memo):
new_obj = self.__class__(copy.deepcopy(self.data, memo))
return new_obj
6. Когда что использовать
| Сценарий | Выбор |
|---|---|
| Нужна полная независимость копии | deepcopy |
| Известно, что вложенные объекты не меняются | copy |
| Работаешь с простыми списками/словарями | list() / dict() |
| Нужна максимальная производительность | ссылка (осторожно!) |
Производительность
import time
import copy
data = [[i] * 1000 for i in range(1000)]
start = time.time()
shallow = copy.copy(data)
print(f"Shallow: {time.time() - start:.6f}s")
start = time.time()
deep = copy.deepcopy(data)
print(f"Deep: {time.time() - start:.6f}s")
# Deep работает медленнее, но гарантирует полную независимость
Вывод
Всегда используй deepcopy если не уверен, нужен copy если явно нужна поверхностная копия. Ошибка в выборе приводит к трудноуловимым багам в production.