232 votes

Comment faire une copie profonde d'une liste ?

Après E0_copy = list(E0) Je suppose. E0_copy est une copie profonde de E0 depuis id(E0) n'est pas égal à id(E0_copy) . Ensuite, je modifie E0_copy dans la boucle, mais pourquoi E0 pas la même après ?

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]]

332voto

Sukrit Kalra Points 11349

E0_copy n'est pas une copie profonde. On ne fait pas de copie profonde en utilisant list() . (Les deux list(...) y testList[:] sont des copies superficielles).

Vous utilisez copy.deepcopy(...) pour copier en profondeur une liste.

deepcopy(x, memo=None, _nil=[])
    Deep copy operation on arbitrary Python objects.

Voir l'extrait suivant -

>>> 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]]

Maintenant, voyez le deepcopy opération

>>> 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]]

Pour expliquer, list(...) ne fait pas de copies récursives des objets internes. Elle ne fait qu'une copie de la liste la plus externe, tout en continuant à référencer les mêmes listes internes. Ainsi, lorsque vous modifiez les listes internes, le changement est reflété à la fois dans la liste originale et dans la copie superficielle. Vous pouvez voir que la copie superficielle fait référence aux listes internes en vérifiant que id(a[0]) == id(b[0])b = list(a) .

91voto

watashiSHUN Points 3213

Je crois que beaucoup de programmeurs ont déjà rencontré un problème d'entretien où on leur demande de copier profondément une liste liée, mais ce problème est plus difficile qu'il n'y paraît !

En Python, il existe un module appelé copy avec deux fonctions utiles :

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

copy() est une fonction de copie superficielle. Si l'argument donné est une structure de données composée, par exemple un fichier liste Python créera alors un autre objet du même type (dans ce cas, un objet nouvelle liste ) mais pour tout ce qui se trouve dans l'ancienne liste, seule leur référence est copiée. Pensez-y comme ça :

newList = [elem for elem in oldlist]

Intuitivement, on pourrait supposer que deepcopy() suivrait le même paradigme, et la seule différence est que pour chaque elem que nous appellerons récursivement deepcopy (tout comme Réponse de mbguy )

mais c'est faux !

deepcopy() préserve en fait la structure graphique des données composées d'origine :

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]

C'est la partie délicate : pendant le processus de deepcopy() Dans le cas des données composées, une table de hachage (dictionnaire en Python) est utilisée pour faire correspondre chaque ancienne référence d'objet à chaque nouvelle référence d'objet, ce qui évite les doublons inutiles et préserve ainsi la structure des données composées copiées.

Documents officiels

26voto

aljgom Points 1116

Si le contenu de la liste est constitué de types de données primitifs, vous pouvez utiliser une compréhension

new_list = [i for i in old_list]

Vous pouvez l'imbriquer pour des listes multidimensionnelles comme :

new_grid = [[i for i in row] for row in grid]

7voto

tailor_raj Points 1009

Si vos éléments de liste sont objets immuables alors vous pouvez utiliser ceci, sinon vous devez utiliser deepcopy de copy module.

vous pouvez également utiliser le chemin le plus court pour la copie profonde d'une list comme ça.

a = [0,1,2,3,4,5,6,7,8,9,10]
b = a[:] #deep copying the list a and assigning it to b
print id(a)
20983280
print id(b)
12967208

a[2] = 20
print a
[0, 1, 20, 3, 4, 5, 6, 7, 8, 9,10]
print b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10]

7voto

mystic Points 147

@Sukrit Kalra

No.1 : list() , [:] , copy.copy() sont tous des copies superficielles. Si un objet est composé, elles ne sont pas toutes adaptées. Vous devez utiliser copy.deepcopy() .

No.2 : b = a directement, a y b ont la même référence, en changeant a est même aussi changeante b .

mettre a à b

si l'assgin a à b directement, a y b partager une référence.

>>> 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]]

copie d'écran

por list()

list() y [:] sont les mêmes. À l'exception des modifications de la première couche, toutes les modifications des autres couches seront transférées.

>>> 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]]

por [:]

>>> 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() et [ :] changent les autres couches, sauf la 1ère couche

# =========== [:] ===========
>>> 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]]

por copy()

Vous constaterez que copy() est identique à la fonction list() y [:] . Ils sont tous copie superficielle .

Pour de plus amples informations sur la copie superficielle et la copie profonde, vous pouvez peut-être vous référer aux documents suivants ici .

>>> 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]]

por 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]]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X