← Все вопросы

Чем list.copy() и срез [:] отличаются от copy.deepcopy для вложенных списков?

Задан 5 месяцев назад741 просмотров2 ответа
15

Скопировал список через b = a[:], поменял элемент во вложенном списке b[0][0] = 99 — и a тоже изменился! Думал, срез делает полную копию. В чём дело и когда нужен deepcopy?

2 ответа

27
✓ Принятый ответ — помог автору

И a[:], и a.copy(), и list(a) делают одно и то же — поверхностную (shallow) копию. Создаётся новый внешний список, но его элементы — это те же самые объекты, что и в оригинале. Если внутри лежат вложенные списки, обе копии ссылаются на одни и те же вложенные списки, поэтому изменение b[0][0] видно и через a.

import copy
a = [[1, 2], [3, 4]]
b = a[:]            # shallow
b[0][0] = 99
print(a)            # [[99, 2], [3, 4]]  — оригинал тоже изменился!

c = copy.deepcopy(a)  # рекурсивно копирует и вложенные
c[0][0] = 0
print(a)            # без изменений

Правило: для плоского списка из чисел/строк хватает среза или .copy(). Как только есть вложенность и вы собираетесь её менять — нужен copy.deepcopy.

Галина Попова Лучшее объяснение разницы shallow/deep, что я видел · 4 месяца назад
Лев Степанов Наконец-то понял, почему мой код «телепатически» менял оригинал · 4 месяца назад
9

Добавлю: b[0][0] = 99 мутирует общий вложенный список, поэтому видно в обоих. А вот b[0] = [99, 2] заменил бы ссылку только в b, и оригинал бы не пострадал — потому что внешний-то список у копии свой. Тонкость, но важная.

Ваш ответ

Войдите, чтобы ответить на вопрос.
Поддержать проект