Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Использование deepcopy в Python
deepcopy (глубокое копирование) — это функция из модуля copy, которая создает полностью независимую копию объекта, включая все вложенные объекты. Это отличается от обычного присваивания и поверхностного копирования (copy.copy()), которые создают лишь ссылки на те же объекты.
Различия между присваиванием, copy и deepcopy
import copy
original = [[1, 2, 3], [4, 5, 6]]
# 1. Простое присваивание — просто ссылка
reference = original
reference[0][0] = 999
print(original) # Output: [[999, 2, 3], [4, 5, 6]] — исходный изменился!
# 2. Поверхностное копирование (shallow copy)
original = [[1, 2, 3], [4, 5, 6]]
shallow = copy.copy(original)
shallow[0][0] = 999
print(original) # Output: [[999, 2, 3], [4, 5, 6]] — все еще изменился!
# 3. Глубокое копирование (deep copy)
original = [[1, 2, 3], [4, 5, 6]]
deep = copy.deepcopy(original)
deep[0][0] = 999
print(original) # Output: [[1, 2, 3], [4, 5, 6]] — исходный не изменился!
Базовый синтаксис
import copy
original = {"name": "Alice", "scores": [10, 20, 30]}
copy_obj = copy.deepcopy(original)
copy_obj["scores"].append(40)
print(original) # Output: {'name': 'Alice', 'scores': [10, 20, 30]}
print(copy_obj) # Output: {'name': 'Alice', 'scores': [10, 20, 30, 40]}
Когда использовать deepcopy
1. Работа со сложными структурами данных
class Student:
def __init__(self, name, grades):
self.name = name
self.grades = grades
student1 = Student("Alice", [4.5, 4.0, 3.8])
student2 = copy.deepcopy(student1)
student2.grades[0] = 5.0
print(student1.grades) # Output: [4.5, 4.0, 3.8]
print(student2.grades) # Output: [5.0, 4.0, 3.8]
2. Работа с словарями и списками
config = {
"database": {
"host": "localhost",
"ports": [5432, 5433]
},
"cache": {
"ttl": 3600
}
}
test_config = copy.deepcopy(config)
test_config["database"]["ports"].append(5434)
print(config["database"]["ports"]) # Output: [5432, 5433]
print(test_config["database"]["ports"]) # Output: [5432, 5433, 5434]
3. Управление состоянием в приложениях
class GameState:
def __init__(self, health, inventory):
self.health = health
self.inventory = inventory
original_state = GameState(100, {"sword": 1, "shield": 1})
save_state = copy.deepcopy(original_state)
original_state.health = 50
original_state.inventory["sword"] = 0
print(save_state.health) # Output: 100
print(save_state.inventory) # Output: {'sword': 1, 'shield': 1}
Производительность и проблемы
deepcopy может быть ресурсоёмким для больших объектов:
import time
big_list = list(range(1000000))
start = time.time()
copy.deepcopy(big_list)
end = time.time()
print(f"deepcopy time: {end - start:.4f} seconds")
start = time.time()
shallow = copy.copy(big_list)
end = time.time()
print(f"copy time: {end - start:.4f} seconds")
Кастомизация копирования
Для контроля над процессом копирования используйте методы __copy__() и __deepcopy__():
class CustomObject:
def __init__(self, data):
self.data = data
def __deepcopy__(self, memo):
print("Custom deepcopy called")
new_obj = CustomObject(copy.deepcopy(self.data, memo))
memo[id(self)] = new_obj
return new_obj
obj = CustomObject([1, 2, 3])
obj_copy = copy.deepcopy(obj) # Output: Custom deepcopy called
Параметр memo — это словарь, который отслеживает уже скопированные объекты, предотвращая бесконечные циклы при циклических ссылках.
Работа с циклическими ссылками
class Node:
def __init__(self, value):
self.value = value
self.next = None
node1 = Node(1)
node2 = Node(2)
node1.next = node2
node2.next = node1 # Циклическая ссылка!
copy_node1 = copy.deepcopy(node1)
print(copy_node1.value) # Output: 1
print(copy_node1.next.value) # Output: 2
print(copy_node1 is copy_node1.next.next) # Output: True
Лучшие практики
- Используйте deepcopy для сложных объектов
- Кэшируйте скопированные объекты, если нужны частые копии
- Профилируйте, если deepcopy часто используется
- Документируйте намерение
- Избегайте лишних копий
deepcopy — мощный инструмент для создания полностью независимых копий объектов.