← Назад к вопросам
При использовании copy копируются ли все вложенности
1.8 Middle🔥 131 комментариев
#Python Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# При использовании copy копируются ли все вложенности?
Нет, обычная copy() (shallow copy) копирует только первый уровень. Вложенные объекты остаются общими ссылками. Для копирования всех вложенностей нужна deepcopy().
1. Shallow Copy (поверхностная копия)
Скопированы только ссылки на вложенные объекты, сами объекты общие.
import copy
# Пример со списком списков
original = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
shallow = copy.copy(original)
print(f"original is shallow: {original is shallow}") # False (разные списки)
print(f"original[0] is shallow[0]: {original[0] is shallow[0]}") # True! (одинаковые подсписки)
# Изменение вложенного списка влияет на оба
shallow[0][0] = 999
print(f"original: {original}") # [[999, 2, 3], [4, 5, 6], [7, 8, 9]]
print(f"shallow: {shallow}") # [[999, 2, 3], [4, 5, 6], [7, 8, 9]]
# Но замена самого подсписка не влияет
shallow[0] = [100, 200, 300]
print(f"original: {original}") # [[999, 2, 3], [4, 5, 6], [7, 8, 9]] — не изменился!
print(f"shallow: {shallow}") # [[100, 200, 300], [4, 5, 6], [7, 8, 9]]
2. Deep Copy (глубокая копия)
Рекурсивно копируются все вложенные объекты.
import copy
original = [[1, 2, 3], [4, 5, 6], {'name': 'Alice', 'scores': [90, 85]}]
deep = copy.deepcopy(original)
print(f"original is deep: {original is deep}") # False
print(f"original[0] is deep[0]: {original[0] is deep[0]}") # False (разные подсписки!)
print(f"original[2] is deep[2]: {original[2] is deep[2]}") # False (разные словари!)
print(f"original[2]['scores'] is deep[2]['scores']: {original[2]['scores'] is deep[2]['scores']}") # False
# Изменения в deep не влияют на original
deep[0][0] = 999
deep[2]['scores'][0] = 50
print(f"original: {original}") # [[1, 2, 3], [4, 5, 6], {'name': 'Alice', 'scores': [90, 85]}]
print(f"deep: {deep}") # [[999, 2, 3], [4, 5, 6], {'name': 'Alice', 'scores': [50, 85]}]
3. Сравнение shallow vs deep
import copy
class Student:
def __init__(self, name, grades):
self.name = name
self.grades = grades # список оценок
def __repr__(self):
return f"Student(name={self.name}, grades={self.grades})"
# Исходный объект
original = Student("Alice", [90, 85, 95])
# Shallow copy
shallow = copy.copy(original)
print(f"original is shallow: {original is shallow}") # False (разные объекты Student)
print(f"original.grades is shallow.grades: {original.grades is shallow.grades}") # True! (одинаковые списки оценок)
# Deep copy
deep = copy.deepcopy(original)
print(f"original is deep: {original is deep}") # False
print(f"original.grades is deep.grades: {original.grades is deep.grades}") # False (разные списки оценок)
# Изменение в shallow
shallow.grades[0] = 50 # Меняем оценку в shallow
print(f"original.grades: {original.grades}") # [50, 85, 95] — изменилась!
print(f"shallow.grades: {shallow.grades}") # [50, 85, 95]
# Изменение в deep
deep.grades[0] = 100
print(f"original.grades: {original.grades}") # [50, 85, 95] — не изменилась
print(f"deep.grades: {deep.grades}") # [100, 85, 95]
4. Практические примеры
❌ Неправильно: shallow copy для конфигурации
import copy
# Конфигурация с вложенными параметрами
base_config = {
'database': {'host': 'localhost', 'port': 5432},
'cache': {'ttl': 3600, 'backends': ['redis', 'memcached']},
'features': {'auth': True, 'api': True}
}
# Создаём копию для другого окружения
dev_config = copy.copy(base_config) # ОШИБКА!
# Меняем host для dev
dev_config['database']['host'] = '127.0.0.1'
print(f"base_config['database']['host']: {base_config['database']['host']}") # '127.0.0.1' — испортили базовую конфиг!
print(f"dev_config['database']['host']: {dev_config['database']['host']}") # '127.0.0.1'
✅ Правильно: deep copy для конфигурации
import copy
base_config = {
'database': {'host': 'localhost', 'port': 5432},
'cache': {'ttl': 3600, 'backends': ['redis', 'memcached']},
'features': {'auth': True, 'api': True}
}
# Глубокая копия для другого окружения
dev_config = copy.deepcopy(base_config) # Правильно!
# Меняем только в dev
dev_config['database']['host'] = '127.0.0.1'
dev_config['cache']['ttl'] = 300
print(f"base_config['database']['host']: {base_config['database']['host']}") # 'localhost' — не испортилась
print(f"base_config['cache']['ttl']: {base_config['cache']['ttl']}") # 3600 — не испортилась
print(f"dev_config['database']['host']: {dev_config['database']['host']}") # '127.0.0.1'
print(f"dev_config['cache']['ttl']: {dev_config['cache']['ttl']}") # 300
5. Копирование словарей и списков
# Для словаря
original_dict = {'a': 1, 'b': [1, 2, 3]}
shallow_dict = original_dict.copy() # Shallow copy
deep_dict = copy.deepcopy(original_dict) # Deep copy
# Для списка
original_list = [1, 2, [3, 4, 5]]
shallow_list = original_list.copy() # Shallow copy
shallow_list2 = original_list[:] # Также shallow copy
deep_list = copy.deepcopy(original_list) # Deep copy
original_list[2][0] = 999
print(f"original_list: {original_list}") # [1, 2, [999, 4, 5]]
print(f"shallow_list: {shallow_list}") # [1, 2, [999, 4, 5]] — испортилась!
print(f"shallow_list2: {shallow_list2}") # [1, 2, [999, 4, 5]] — испортилась!
print(f"deep_list: {deep_list}") # [1, 2, [3, 4, 5]] — осталась целой
6. Производительность
import copy
import time
# Большая структура с вложенностями
big_data = [{'id': i, 'values': list(range(100))} for i in range(10000)]
# Shallow copy быстрее
start = time.time()
for _ in range(1000):
copy.copy(big_data)
shallow_time = time.time() - start
# Deep copy медленнее
start = time.time()
for _ in range(1000):
copy.deepcopy(big_data)
deep_time = time.time() - start
print(f"Shallow copy: {shallow_time:.4f} сек")
print(f"Deep copy: {deep_time:.4f} сек")
print(f"Deep copy медленнее в {deep_time / shallow_time:.1f}x раз")
Таблица сравнения
| Операция | Shallow Copy | Deep Copy |
|---|---|---|
| Копирует весь объект | Да (только 1-й уровень) | Да (рекурсивно все уровни) |
| Копирует вложенные объекты | Нет (общие ссылки) | Да (новые копии) |
| Скорость | Быстро | Медленно |
| Память | Меньше | Больше |
| Безопасность | Низкая (изменения влияют) | Высокая (независимые копии) |
| Используется | Редко в production | Часто для безопасности данных |
Когда использовать?
import copy
# Используй shallow copy только когда:
# 1. Уверен, что не будешь менять вложенные объекты
# 2. Нужна максимальная производительность
users_refs = original_users.copy() # OK если только читаешь
# Используй deep copy когда:
# 1. Нужны полностью независимые копии
# 2. Мутируешь вложенные данные
# 3. Работаешь с конфигурациями, кэшами
safe_config = copy.deepcopy(original_config) # Правильно!
Вывод
copy.copy() копирует только первый уровень. Вложенные объекты остаются общими ссылками. Используй copy.deepcopy() для полного копирования всех вложенностей, если не хочешь неожиданных побочных эффектов при изменении данных.