← Назад к вопросам

Как использовать deepcopy в Python?

2.0 Middle🔥 191 комментариев
#Python Core

Комментарии (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

Лучшие практики

  1. Используйте deepcopy для сложных объектов
  2. Кэшируйте скопированные объекты, если нужны частые копии
  3. Профилируйте, если deepcopy часто используется
  4. Документируйте намерение
  5. Избегайте лишних копий

deepcopy — мощный инструмент для создания полностью независимых копий объектов.