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

Что такое copy?

2.3 Middle🔥 151 комментариев
#Python Core#Soft Skills

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Copy в Python

Copy — это встроенный модуль Python, который предоставляет функции для создания копий объектов. Это критически важно для понимания того, как работают ссылки и значения в Python, особенно при работе с изменяемыми структурами данных (списки, словари, множества).

Проблема без copy

В Python все переменные — это ссылки на объекты. При присваивании создаётся не новый объект, а новая ссылка на тот же объект:

# Без копирования — обе переменные указывают на один объект
original_list = [1, 2, 3]
copy_list = original_list

copy_list.append(4)
print(original_list)  # [1, 2, 3, 4] — изменилась оригинальная!
print(copy_list)      # [1, 2, 3, 4]

Это приводит к непредвиденным побочным эффектам. Модуль copy решает эту проблему.

Функции модуля copy

copy.copy() — поверхностная копия (Shallow Copy):

import copy

original = [1, 2, 3]
shallow = copy.copy(original)

shallow.append(4)
print(original)  # [1, 2, 3] — не изменилась
print(shallow)   # [1, 2, 3, 4]

Для вложенных структур shallow copy копирует только первый уровень:

import copy

original = [[1, 2], [3, 4]]
shallow = copy.copy(original)

# Изменение вложенного списка влияет на оригинал
shallow[0].append(999)
print(original)  # [[1, 2, 999], [3, 4]] — вложенная часть изменилась!
print(shallow)   # [[1, 2, 999], [3, 4]]

copy.deepcopy() — глубокая копия (Deep Copy):

import copy

original = [[1, 2], [3, 4]]
deep = copy.deepcopy(original)

# Изменение вложенного списка НЕ влияет на оригинал
deep[0].append(999)
print(original)  # [[1, 2], [3, 4]] — не изменилась
print(deep)      # [[1, 2, 999], [3, 4]]

Различия между способами копирования

import copy

original = {"user": {"name": "Alice", "age": 30}}

# 1. Присваивание — одна ссылка
assignment = original

# 2. Поверхностная копия
shallow = copy.copy(original)

# 3. Глубокая копия
deep = copy.deepcopy(original)

# Изменяем вложенный словарь
deep["user"]["name"] = "Bob"

print(original)  # {'user': {'name': 'Alice', 'age': 30}} — не изменилась
print(shallow)   # {'user': {'name': 'Bob', 'age': 30}} — изменилась!
print(deep)      # {'user': {'name': 'Bob', 'age': 30}}
print(assignment) # {'user': {'name': 'Bob', 'age': 30}} — изменилась!

Практические примеры

Работа со списками и словарями:

import copy

# Копирование списков
original_items = ["apple", "banana", "cherry"]
backup = copy.copy(original_items)
original_items.remove("banana")

print(original_items)  # ['apple', 'cherry']
print(backup)          # ['apple', 'banana', 'cherry']

# Копирование словарей
original_config = {"host": "localhost", "port": 5432}
config_backup = copy.copy(original_config)
original_config["port"] = 3306

print(original_config)  # {'host': 'localhost', 'port': 3306}
print(config_backup)    # {'host': 'localhost', 'port': 5432}

Сохранение снимков состояния:

import copy

class Game:
    def __init__(self):
        self.player_state = {"health": 100, "level": 1}
        self.history = []
    
    def take_damage(self, damage):
        # Сохраняем снимок перед изменением
        self.history.append(copy.deepcopy(self.player_state))
        self.player_state["health"] -= damage
    
    def undo(self):
        if self.history:
            self.player_state = self.history.pop()

game = Game()
game.take_damage(30)
game.take_damage(20)
print(game.player_state)  # {'health': 50, 'level': 1}
game.undo()
print(game.player_state)  # {'health': 70, 'level': 1}

Параметры функций:

import copy

def process_data(data):
    # Если не скопировать, функция изменит оригинальный список
    data = copy.deepcopy(data)
    data.append("processed")
    return data

original = ["item1", "item2"]
result = process_data(original)

print(original)  # ['item1', 'item2'] — не изменилась
print(result)    # ['item1', 'item2', 'processed']

Когда использовать shallow vs deep copy

Shallow copy достаточно:

  • Работа с простыми (не вложенными) структурами
  • Работа с неизменяемыми объектами (int, str, tuple)
  • Когда нужна быстрая операция
import copy
users = ["Alice", "Bob", "Charlie"]
users_copy = copy.copy(users)  # Достаточно shallow

Deep copy необходим:

  • Вложенные структуры (списки списков, словари со словарями)
  • Сложные объекты с отношениями
  • Когда нужна полная независимость копии
import copy
complex_data = [[1, 2], [3, 4], {"nested": [5, 6]}]
complex_copy = copy.deepcopy(complex_data)  # Необходим deep

Альтернативы для встроенных типов

# Для списков
original = [1, 2, 3]
copy1 = original.copy()  # Поверхностная копия
copy2 = original[:]      # Слайс создаёт копию
copy3 = list(original)   # Конструктор создаёт копию

# Для словарей
original = {"a": 1, "b": 2}
copy1 = original.copy()  # Поверхностная копия
copy2 = dict(original)   # Конструктор создаёт копию

Производительность

import copy
import timeit

data = list(range(10000))

# Shallow copy быстрее
time_shallow = timeit.timeit(lambda: copy.copy(data), number=1000)
print(f"Shallow: {time_shallow}")

# Deep copy медленнее
time_deep = timeit.timeit(lambda: copy.deepcopy(data), number=1000)
print(f"Deep: {time_deep}")  # Примерно в 10-100 раз медленнее

Copy — это фундаментальный инструмент для избежания непредвиденных побочных эффектов при работе с изменяемыми объектами в Python, обеспечивая контроль над тем, когда объекты действительно копируются.