Вопрос-Ответ

How to deep copy a list?

Как скопировать список вглубь?

После E0_copy = list(E0), я думаю, E0_copy это глубокая копия E0 поскольку id(E0) не равно id(E0_copy). Затем я изменяю E0_copy в цикле, но почему после этого E0 не то же самое?

E0 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for k in range(3):
E0_copy = list(E0)
E0_copy[k][k] = 0
#print(E0_copy)
print E0 # -> [[0, 2, 3], [4, 0, 6], [7, 8, 0]]
Переведено автоматически
Ответ 1

E0_copy это не глубокое копирование. Вы не создаете глубокое копирование с помощью list(). (Оба list(...) и testList[:] являются мелкими копиями, так же как testList.copy().)

Вы используете copy.deepcopy(...) для глубокого копирования списка.


copy.deepcopy(x[, memo])


Возвращает глубокую копию x.


Смотрите следующий фрагмент -

>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b # b changes too -> Not a deepcopy.
[[1, 10, 3], [4, 5, 6]]

Теперь посмотрите на deepcopy операцию

>>> import copy
>>> b = copy.deepcopy(a)
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]
>>> a[0][1] = 9
>>> a
[[1, 9, 3], [4, 5, 6]]
>>> b # b doesn't change -> Deep Copy
[[1, 10, 3], [4, 5, 6]]

Чтобы объяснить, list(...) не создает рекурсивно копии внутренних объектов. Он создает копию только самого внешнего списка, продолжая ссылаться на те же внутренние списки, следовательно, когда вы изменяете внутренние списки, изменение отражается как в исходном списке, так и в мелкой копии. Вы можете увидеть, что неглубокое копирование ссылается на внутренние списки, проверив это id(a[0]) == id(b[0]) где b = list(a).

Ответ 2

В Python есть модуль под названием copy с двумя полезными функциями:

import copy
copy.copy()
copy.deepcopy()

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

newList = [elem for elem in oldlist]

Интуитивно мы могли бы предположить, что deepcopy() будет следовать той же парадигме, и единственная разница заключается в том, что для каждого элемента мы будем рекурсивно вызывать deepcopy, (точно так же, как ответ mbguy)

но это неправильно!

deepcopy() фактически сохраняется графическая структура исходных составных данных:

a = [1,2]
b = [a,a] # there's only 1 object a
c = deepcopy(b)

# check the result
c[0] is a # False, a new object a_1 is created
c[0] is c[1] # True, c is [a_1, a_1] not [a_1, a_2]

Это сложная часть: в процессе deepcopy() используется хэш-таблица (словарь в Python) для сопоставления каждого старого объекта ref с каждым новым объектом ref, что предотвращает ненужные дублирования и, таким образом, сохраняет структуру скопированных составных данных.

Официальные документы

Ответ 3

Если содержимое списка представляет собой примитивные типы данных, вы можете использовать понимание

new_list = [i for i in old_list]

Вы можете вложить его в многомерные списки, такие как:

new_grid = [[i for i in row] for row in grid]
Ответ 4

@Sukrit Kalra

№ 1: list(), [:], copy.copy() все они являются мелкой копией. Если объект составной, все они не подходят. Вам нужно использовать copy.deepcopy().

№2: b = a напрямую, a и b имеют одну и ту же ссылку, изменение a равносильно изменению b.

установите a в b

если хотите a использовать b напрямую, a и b поделитесь одной ссылкой.

>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = a
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0] = 1
>>> a
[1, [4, 5, 6]]
>>> b
[1, [4, 5, 6]]


>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = a
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]

теневое копирование

Автор: list()

list() и [:] одинаковы. За исключением изменений первого слоя, будут перенесены изменения всех остальных слоев.

>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0] = 1
>>> a
[1, [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]


>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]

Автор: [:]

>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = a[:]
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0] = 1
>>> a
[1, [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]


>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = a[:]
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]

list() и [:] изменяют другие слои, за исключением 1-го слоя

# =========== [:] ===========
>>> a = [[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b = a[:]
>>> a
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> a[0][2] = 4
>>> a
[[1, 2, 4], [4, 5, 6]]
>>> b
[[1, 2, 4], [4, 5, 6]]


>>> a = [[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b = a[:]
>>> a
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> a[0][2][0] = 999
>>> a
[[1, 2, [999, 6]], [4, 5, 6]]
>>> b
[[1, 2, [999, 6]], [4, 5, 6]]



# =========== list() ===========
>>> a = [[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> a[0][2] = 4
>>> a
[[1, 2, 4], [4, 5, 6]]
>>> b
[[1, 2, 4], [4, 5, 6]]


>>> a = [[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> a[0][2][0] = 999
>>> a
[[1, 2, [999, 6]], [4, 5, 6]]
>>> b
[[1, 2, [999, 6]], [4, 5, 6]]

Автор: copy()

Вы обнаружите, что copy() функция такая же, как list() и [:]. Все они являются мелким копированием.

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

>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = copy.copy(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]

Автор: deepcopy()

>>> import copy
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = copy.deepcopy(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0] = 1
>>> a
[1, [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]


>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = copy.deepcopy(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]

2023-10-23 08:42 python list