Копирование списка с помощью [:] или copy() в python неглубоко?

Скажем, у меня есть список a с некоторыми значениями, и я сделал b = a[:]. Тогда изменение содержимого списка b не изменит список a в соответствии с тем, что я прочитал. Таким образом, это означает, что это глубокая копия. Но документация python по-прежнему относится к этому как мелкая копия. Может ли кто-то очистить это для меня?

4 ответа

Чтобы продемонстрировать, что означает мелкая копия:

a = [ [1,2], [3,4,5] ]
b = a[:] # make a shallow copy
a is b # not the same object, because this is a copy
=> False
a == b # same value, because this is a copy
=> True
a[0] is b[0] # elements are the *same objects*, because this is a *shallow* copy
=> True

Изменение структуры a не будет отражено в b, потому что это копия:

a.pop()
len(a)
=> 1
len(b)
=> 2

Чтобы продемонстрировать отличие от глубокой копии: изменение объекта, содержащегося в a (в отличие от структуры a) на месте, отражается в b, потому что b ссылается на те же объекты, что и a.

a[0][0] = 'XYZ'
b[0]
=> ['XYZ', 2]


Из python docs

Разница между мелким и глубоким копированием имеет значение только для составные объекты (объекты, которые содержат другие объекты, например списки или класса):

Неглубокая копия создает новый составной объект, а затем (к насколько возможно) вставляет ссылки в него на объекты, найденные в оригинал. Глубокая копия создает новый составной объект, а затем, рекурсивно вставляет в него копии объектов, найденных в оригинал.

Мелкая копия создает новый объект только для верхнего уровня/объекта, а затем копирует по ссылке все под-объекты. Deep copy создает новый объект для верхнего объекта/уровня и для всех под-объектов.


Тогда изменение содержимого списка "b" не изменит список "a" в соответствии с тем, что я прочитал. Таким образом, это означает его глубокую копию.

Нет, это не так. Неглубокая копия отличается от глубокой копии тем, скопированы ли скопированные значения или нет.

В вашем случае список копируется, но два результирующих списка будут содержать одни и те же объекты. Добавление или удаление значения в одном списке не повлияет на другой список, но изменения в содержащемся объекте будут отражены.


Тогда изменение содержимого списка "b" не изменит список "a" в соответствии с тем, что я прочитал.

Как и в случае, если вы вынимаете часть содержимого или выключаете его для другого содержимого, это не повлияет на a. Мутации для объектов, хранящихся в b, будут видны через оба списка, потому что в обоих списках хранятся одни и те же объекты.

>>> class Mutable(object):
... def __init__(self, x):
... self.x = x
... def __repr__(self):
... return 'Mutable({})'.format(self.x)
...
>>> a = [Mutable(1), Mutable(2)]
>>> b = a[:]
>>> del b[1] # Doesn't affect a
>>> a
[Mutable(1), Mutable(2)]
>>> b[0].x = 5 # Visible through a
>>> a
[Mutable(5), Mutable(2)]

licensed under cc by-sa 3.0 with attribution.