Was ist der Unterschied zwischen Flachkopie, Deepcopy und normalem Zuweisungsbetrieb?

210
import copy

a = "deepak"
b = 1, 2, 3, 4
c = [1, 2, 3, 4]
d = {1: 10, 2: 20, 3: 30}

a1 = copy.copy(a)
b1 = copy.copy(b)
c1 = copy.copy(c)
d1 = copy.copy(d)


print("immutable - id(a)==id(a1)", id(a) == id(a1))
print("immutable - id(b)==id(b1)", id(b) == id(b1))
print("mutable - id(c)==id(c1)", id(c) == id(c1))
print("mutable - id(d)==id(d1)", id(d) == id(d1))

Ich erhalte folgende Ergebnisse:

immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False

Wenn ich eine Deepcopy durchführe:

a1 = copy.deepcopy(a)
b1 = copy.deepcopy(b)
c1 = copy.deepcopy(c)
d1 = copy.deepcopy(d)

Ergebnisse sind die gleichen:

immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False

Wenn ich an Zuweisungsoperationen arbeite:

a1 = a
b1 = b
c1 = c
d1 = d

dann sind die Ergebnisse:

immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) True
mutable - id(d)==id(d1) True

Kann jemand erklären, was genau den Unterschied zwischen den Kopien ausmacht? Hat es etwas mit veränderlichen und unveränderlichen Objekten zu tun? Wenn ja, können Sie es mir bitte erklären?

Deeshank
quelle

Antworten:

364

Normale Zuweisungsoperationen zeigen die neue Variable einfach auf das vorhandene Objekt. Die Dokumente erklären den Unterschied zwischen flachen und tiefen Kopien:

Der Unterschied zwischen flachem und tiefem Kopieren ist nur für zusammengesetzte Objekte relevant (Objekte, die andere Objekte enthalten, wie Listen oder Klasseninstanzen):

  • Eine flache Kopie erstellt ein neues zusammengesetztes Objekt und fügt dann (soweit möglich) Verweise auf die im Original gefundenen Objekte ein.

  • Eine tiefe Kopie erstellt ein neues zusammengesetztes Objekt und fügt dann rekursiv Kopien der im Original gefundenen Objekte ein.

Hier ist eine kleine Demonstration:

import copy

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

Kopieren mit normalen Zuweisungsoperationen:

d = c

print id(c) == id(d)          # True - d is the same object as c
print id(c[0]) == id(d[0])    # True - d[0] is the same object as c[0]

Verwenden einer flachen Kopie:

d = copy.copy(c)

print id(c) == id(d)          # False - d is now a new object
print id(c[0]) == id(d[0])    # True - d[0] is the same object as c[0]

Verwenden einer tiefen Kopie:

d = copy.deepcopy(c)

print id(c) == id(d)          # False - d is now a new object
print id(c[0]) == id(d[0])    # False - d[0] is now a new object
grc
quelle
5
Ist Assginment dasselbe wie flache Kopie?
Deeshank
35
@Dshank Nein. Eine flache Kopie erstellt ein neues Objekt, während eine Zuweisung die neue Variable einfach auf das vorhandene Objekt verweist. Alle Änderungen am vorhandenen Objekt wirken sich auf beide Variablen aus (mit Zuweisung).
grc
13
@grc "Alle Änderungen am vorhandenen Objekt wirken sich auf beide Variablen aus (mit Zuweisung)" - Diese Anweisung gilt nur für veränderbare Objekte und nicht für unveränderliche Typen wie Zeichenfolge, Float, Tupel.
Neerav
1
@grc Aber ich habe ein Beispiel ausprobiert (ich entferne die neue Zeile hier.) list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8] print(list_) print(newlist)Die newlistStandbildanzeige [[1, 2], [3, 4]]. Ist list_[0]aber eine Liste, die veränderlich ist.
Alston
1
@Stallman list_[0]ist veränderbar, aber Sie mutieren / modifizieren es nicht. Versuchen Sie es list_[0].append(9)oder list_[0][0] = 7stattdessen.
grc
46

Bei unveränderlichen Objekten ist kein Kopieren erforderlich, da sich die Daten niemals ändern. Daher verwendet Python dieselben Daten. IDs sind immer gleich. Bei veränderlichen Objekten erstellt [flache] Kopie ein neues Objekt, da sie sich möglicherweise ändern können.

Deep Copy bezieht sich auf verschachtelte Strukturen. Wenn Sie eine Liste mit Listen haben, copieskopieren Sie auch die verschachtelten Listen tief , sodass es sich um eine rekursive Kopie handelt. Mit nur kopieren haben Sie eine neue äußere Liste, aber innere Listen sind Referenzen.

Die Zuordnung wird nicht kopiert. Es wird einfach der Verweis auf die alten Daten gesetzt. Sie benötigen also eine Kopie, um eine neue Liste mit demselben Inhalt zu erstellen.

perreal
quelle
With just copy, you have a new outer list but inner lists are references.Würde die kopierte Liste für die inneren Listen von der ursprünglichen beeinflusst? Ich erstelle eine Liste mit Listen wie list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8]und die newlistbleiben gleich. Handelt es sich bei der inneren Liste also um Referenzen?
Alston
1
@Stallman Sie ändern hier nicht die Liste, auf die verwiesen wird. Sie erstellen lediglich eine neue Liste und weisen sie als erstes Element einer der Kopien zu. versuchen Sie eslist_[0][0] = 7
Perreal
20

Bei unveränderlichen Objekten ist das Erstellen einer Kopie wenig sinnvoll, da sie sich nicht ändern werden. Für veränderbare Objekte assignment, copyund deepcopyverhält sich anders. Sprechen wir über jeden von ihnen mit Beispielen.

Eine Zuweisungsoperation weist einfach die Referenz der Quelle dem Ziel zu, z.

>>> i = [1,2,3]
>>> j=i
>>> hex(id(i)), hex(id(j))
>>> ('0x10296f908', '0x10296f908') #Both addresses are identical

Jetzt iund jtechnisch bezieht sich auf die gleiche Liste. Beide iund jhaben die gleiche Speicheradresse. Jede Aktualisierung eines der beiden wird auf den anderen übertragen. z.B:

>>> i.append(4)
>>> j
>>> [1,2,3,4] #Destination is updated

>>> j.append(5)
>>> i
>>> [1,2,3,4,5] #Source is updated

Auf der anderen Seite copyund deepcopyerstellt eine neue Kopie der Variablen. Änderungen an der ursprünglichen Variablen werden nun nicht mehr in die Kopiervariable übernommen und umgekehrt. Erstellen Sie copy(shallow copy)jedoch keine Kopie verschachtelter Objekte, sondern kopieren Sie nur die Referenz verschachtelter Objekte. Deepcopy kopiert alle verschachtelten Objekte rekursiv.

Einige Beispiele zur Demonstration des Verhaltens von copyund deepcopy:

Beispiel für eine flache Liste mit copy:

>>> import copy
>>> i = [1,2,3]
>>> j = copy.copy(i)
>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are different

>>> i.append(4)
>>> j
>>> [1,2,3] #Updation of original list didn't affected copied variable

Beispiel für eine verschachtelte Liste mit copy:

>>> import copy
>>> i = [1,2,3,[4,5]]
>>> j = copy.copy(i)

>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are still different

>>> hex(id(i[3])), hex(id(j[3]))
>>> ('0x10296f908', '0x10296f908') #Nested lists have same address

>>> i[3].append(6)
>>> j
>>> [1,2,3,[4,5,6]] #Updation of original nested list updated the copy as well

Beispiel für eine flache Liste mit deepcopy:

>>> import copy
>>> i = [1,2,3]
>>> j = copy.deepcopy(i)
>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are different

>>> i.append(4)
>>> j
>>> [1,2,3] #Updation of original list didn't affected copied variable

Beispiel für eine verschachtelte Liste mit deepcopy:

>>> import copy
>>> i = [1,2,3,[4,5]]
>>> j = copy.deepcopy(i)

>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are still different

>>> hex(id(i[3])), hex(id(j[3]))
>>> ('0x10296f908', '0x102b9b7c8') #Nested lists have different addresses

>>> i[3].append(6)
>>> j
>>> [1,2,3,[4,5]] #Updation of original nested list didn't affected the copied variable    
Sohaib Farooqi
quelle
18

Lassen Sie uns in einem grafischen Beispiel sehen, wie der folgende Code ausgeführt wird:

import copy

class Foo(object):
    def __init__(self):
        pass


a = [Foo(), Foo()]
shallow = copy.copy(a)
deep = copy.deepcopy(a)

Geben Sie hier die Bildbeschreibung ein

user1767754
quelle
5

a, b, c, d, a1, b1, c1 und d1 sind Verweise auf Objekte im Speicher, die durch ihre IDs eindeutig identifiziert werden.

Eine Zuweisungsoperation nimmt einen Verweis auf das Objekt im Speicher und weist diesen Verweis einem neuen Namen zu. c=[1,2,3,4]ist eine Zuweisung, die ein neues Listenobjekt erstellt, das diese vier Ganzzahlen enthält, und dem der Verweis auf dieses Objekt zugewiesen wird c. c1=cist eine Zuweisung, die denselben Verweis auf dasselbe Objekt verwendet und diesen zuweist c1. Da die Liste veränderbar ist, ist alles, was mit dieser Liste passiert, sichtbar, unabhängig davon, ob Sie über coder darauf zugreifen c1, da beide auf dasselbe Objekt verweisen.

c1=copy.copy(c)ist eine "flache Kopie", die eine neue Liste erstellt und der neuen Liste den Verweis zuweist c1. czeigt immer noch auf die ursprüngliche Liste. Wenn Sie also die Liste unter ändern, ändert sich die Liste c1, auf die verwiesen cwird, nicht.

Das Konzept des Kopierens ist für unveränderliche Objekte wie Ganzzahlen und Zeichenfolgen irrelevant. Da Sie diese Objekte nicht ändern können, müssen niemals zwei Kopien desselben Werts an verschiedenen Speicherorten gespeichert werden. Ganzzahlen und Zeichenfolgen sowie einige andere Objekte, für die das Konzept des Kopierens nicht gilt, werden einfach neu zugewiesen. Deshalb ist Ihre Beispiele mit aund bErgebnis in identischen IDs.

c1=copy.deepcopy(c)ist eine "tiefe Kopie", funktioniert aber in diesem Beispiel genauso wie eine flache Kopie. Tiefe Kopien unterscheiden sich von flachen Kopien darin, dass flache Kopien eine neue Kopie des Objekts selbst erstellen , aber alle Verweise innerhalb dieses Objekts selbst nicht kopiert werden. In Ihrem Beispiel enthält Ihre Liste nur Ganzzahlen (die unveränderlich sind), und wie bereits erwähnt, müssen diese nicht kopiert werden. Der "tiefe" Teil der tiefen Kopie gilt also nicht. Betrachten Sie jedoch diese komplexere Liste:

e = [[1, 2],[4, 5, 6],[7, 8, 9]]

Dies ist eine Liste, die andere Listen enthält (Sie können sie auch als zweidimensionales Array beschreiben).

Wenn Sie eine "flache Kopie" ausführen eund in diese kopieren e1, werden Sie feststellen, dass sich die ID der Liste ändert, aber jede Kopie der Liste Verweise auf dieselben drei Listen enthält - die Listen mit Ganzzahlen. Das heißt, wenn Sie es tun würden e[0].append(3), dann ewäre es [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. Wäre e1aber auch so [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. Auf der anderen Seite, wenn Sie später tun e.append([10, 11, 12]), ewäre [[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12]]. aber e1noch[[1, 2, 3],[4, 5, 6],[7, 8, 9]] . Dies liegt daran, dass die äußeren Listen separate Objekte sind, die anfänglich jeweils drei Verweise auf drei innere Listen enthalten. Wenn Sie die inneren Listen ändern, können Sie diese Änderungen sehen, unabhängig davon, ob Sie sie durch die eine oder andere Kopie anzeigen. Wenn Sie jedoch eine der äußeren Listen wie oben ändern, danneenthält drei Verweise auf die ursprünglichen drei Listen sowie einen weiteren Verweis auf eine neue Liste. Und e1enthält immer noch nur die ursprünglichen drei Referenzen.

Eine "tiefe Kopie" würde nicht nur die äußere Liste duplizieren, sondern auch in die Listen gehen und die inneren Listen duplizieren, so dass die beiden resultierenden Objekte keine der gleichen Referenzen enthalten (was veränderbare Objekte betrifft). . Wenn die inneren Listen weitere Listen (oder andere Objekte wie Wörterbücher) enthalten würden, würden auch diese dupliziert. Das ist der "tiefe" Teil der "tiefen Kopie".

Andrew Gorcester
quelle
2

Wenn wir in Python einem anderen Objekt Objekte wie Liste, Tupel, Diktat usw. zuweisen, normalerweise mit einem '=' - Zeichen, erstellt Python Kopien als Referenz . Nehmen wir an, wir haben eine Liste mit folgenden Listen:

list1 = [ [ 'a' , 'b' , 'c' ] , [ 'd' , 'e' , 'f' ]  ]

und wir weisen dieser Liste eine andere Liste zu, wie:

list2 = list1

Wenn wir dann list2 im Python-Terminal drucken, erhalten wir Folgendes:

list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ']  ]

Sowohl list1 als auch list2 zeigen auf denselben Speicherort. Jede Änderung an einem dieser Speicherorte führt zu Änderungen, die in beiden Objekten sichtbar sind, dh beide Objekte zeigen auf denselben Speicherort. Wenn wir list1 so ändern:

list1[0][0] = 'x’
list1.append( [ 'g'] )

dann sind sowohl list1 als auch list2:

list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g'] ]
list2 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g’ ] ]

Jetzt zu kommen flache Kopie , wenn zwei Objekte über flache Kopie kopiert werden, bezieht sich das untergeordnete Objekt von beiden Elternobjekt zu gleichen Speicherplatz , aber keine neuen Änderungen in einem der kopierte Objekt wird unabhängig voneinander sein. Lassen Sie uns dies anhand eines kleinen Beispiels verstehen. Angenommen, wir haben dieses kleine Code-Snippet:

import copy

list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ']  ]      # assigning a list
list2 = copy.copy(list1)       # shallow copy is done using copy function of copy module

list1.append ( [ 'g', 'h', 'i'] )   # appending another list to list1

print list1
list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ]
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] ]

Beachten Sie, dass list2 nicht betroffen ist. Wenn wir jedoch Änderungen an untergeordneten Objekten vornehmen, wie z.

list1[0][0] = 'x’

dann werden sowohl list1 als auch list2 geändert:

list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ] 
list2 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] ]

Jetzt hilft Deep Copy dabei , vollständig isolierte Objekte voneinander zu erstellen. Wenn zwei Objekte über Deep Copy kopiert werden, zeigen sowohl das übergeordnete als auch das untergeordnete Objekt auf einen anderen Speicherort. Beispiel:

import copy

list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ']  ]         # assigning a list
list2 = deepcopy.copy(list1)       # deep copy is done using deepcopy function of copy module

list1.append ( [ 'g', 'h', 'i'] )   # appending another list to list1

print list1
list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ]
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] ]

Beachten Sie, dass list2 nicht betroffen ist. Wenn wir jedoch Änderungen an untergeordneten Objekten vornehmen, wie z.

list1[0][0] = 'x’

dann bleibt auch list2 unberührt, da alle untergeordneten Objekte und übergeordneten Objekte auf unterschiedliche Speicherorte verweisen:

list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ] 
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f  ' ] ]

Ich hoffe es hilft.

Nitish Chauhan
quelle
0

Der folgende Code zeigt den Unterschied zwischen Zuweisung, flacher Kopie mit der Kopiermethode, flacher Kopie mit (Slice) [:] und Deepcopy. Im folgenden Beispiel werden verschachtelte Listen verwendet, um die Unterschiede deutlicher zu machen.

from copy import deepcopy

########"List assignment (does not create a copy) ############
l1 = [1,2,3, [4,5,6], [7,8,9]]
l1_assigned = l1

print(l1)
print(l1_assigned)

print(id(l1), id(l1_assigned))
print(id(l1[3]), id(l1_assigned[3]))
print(id(l1[3][0]), id(l1_assigned[3][0]))

l1[3][0] = 100
l1.pop(4)
l1.remove(1)


print(l1)
print(l1_assigned)
print("###################################")

########"List copy using copy method (shallow copy)############

l2 = [1,2,3, [4,5,6], [7,8,9]]
l2_copy = l2.copy()

print(l2)
print(l2_copy)

print(id(l2), id(l2_copy))
print(id(l2[3]), id(l2_copy[3]))
print(id(l2[3][0]), id(l2_copy[3][0]))
l2[3][0] = 100
l2.pop(4)
l2.remove(1)


print(l2)
print(l2_copy)

print("###################################")

########"List copy using slice (shallow copy)############

l3 = [1,2,3, [4,5,6], [7,8,9]]
l3_slice = l3[:]

print(l3)
print(l3_slice)

print(id(l3), id(l3_slice))
print(id(l3[3]), id(l3_slice[3]))
print(id(l3[3][0]), id(l3_slice[3][0]))

l3[3][0] = 100
l3.pop(4)
l3.remove(1)


print(l3)
print(l3_slice)

print("###################################")

########"List copy using deepcopy ############

l4 = [1,2,3, [4,5,6], [7,8,9]]
l4_deep = deepcopy(l4)

print(l4)
print(l4_deep)

print(id(l4), id(l4_deep))
print(id(l4[3]), id(l4_deep[3]))
print(id(l4[3][0]), id(l4_deep[3][0]))

l4[3][0] = 100
l4.pop(4)
l4.remove(1)

print(l4)
print(l4_deep)
print("##########################")
print(l4[2], id(l4[2]))
print(l4_deep[3], id(l4_deep[3]))

print(l4[2][0], id(l4[2][0]))
print(l4_deep[3][0], id(l4_deep[3][0]))
Sandeep
quelle
0

Der GIST lautet wie folgt: Der Umgang mit flachen Listen (keine Unterlisten, nur einzelne Elemente) mit "normaler Zuordnung" führt zu einem "Nebeneffekt", wenn Sie eine flache Liste erstellen und dann eine Kopie dieser Liste mit "normaler Zuordnung" erstellen. . Dieser "Nebeneffekt" tritt auf, wenn Sie ein Element der erstellten Kopierliste ändern, da automatisch dieselben Elemente der ursprünglichen Liste geändert werden. Dies ist copypraktisch, da die ursprünglichen Listenelemente beim Ändern der Kopierelemente nicht geändert werden.

Auf der anderen Seite hat copydies auch einen "Nebeneffekt", wenn Sie eine Liste mit Listen (Unterlisten) haben und diese deepcopylösen. Wenn Sie beispielsweise eine große Liste mit verschachtelten Listen (Unterlisten) erstellen und eine Kopie dieser großen Liste (der ursprünglichen Liste) erstellen. Der "Nebeneffekt" würde auftreten, wenn Sie die Unterlisten der Kopierliste ändern, wodurch die Unterlisten der großen Liste automatisch geändert werden. Manchmal (in einigen Projekten) möchten Sie die große Liste (Ihre ursprüngliche Liste) unverändert lassen, und Sie möchten lediglich eine Kopie ihrer Elemente (Unterlisten) erstellen. Zu deepcopydiesem Zweck verwenden Sie eine Lösung, die diesen "Nebeneffekt" beseitigt und eine Kopie erstellt, ohne den ursprünglichen Inhalt zu ändern.

Das unterschiedliche Verhalten copyund die unterschiedlichen deep copyOperationen betreffen nur zusammengesetzte Objekte (dh Objekte, die andere Objekte wie Listen enthalten).

In diesem einfachen Codebeispiel sind die Unterschiede dargestellt:

Zuerst

Lassen Sie uns überprüfen, wie sich copy(flach) verhält, indem wir eine Originalliste und eine Kopie dieser Liste erstellen:

import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.copy(original_list)

Lassen Sie uns nun einige printTests durchführen und sehen, wie sich die ursprüngliche Liste im Vergleich zur Kopierliste verhält:

original_list und copy_list haben unterschiedliche Adressen

print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328

Elemente von original_list und copy_list haben die gleichen Adressen

print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440

Unterelemente von original_list und copy_list haben die gleichen Adressen

print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x1faef08 0x1faef08

Durch Ändern der Elemente von original_list werden die Elemente von copy_list NICHT geändert

original_list.append(6)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]

Durch Ändern von copy_list-Elementen werden original_list-Elemente NICHT geändert

copy_list.append(7)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]

Ändern von original_list-Unterelementen Ändern Sie automatisch copy_list-Unterelemente

original_list[5].append('c')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 7]

Ändern von copy_list-Unterelementen Ändern Sie automatisch original_list-Unterelemente

copy_list[5].append('d')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 7]

Zweite

Lassen Sie uns überprüfen, wie deepcopywir uns verhalten, indem wir dasselbe tun wie bei copy(Erstellen einer Originalliste und einer Kopie dieser Liste):

import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.copy(original_list)

Lassen Sie uns nun einige printTests durchführen und sehen, wie sich die ursprüngliche Liste im Vergleich zur Kopierliste verhält:

import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.deepcopy(original_list)

original_list und copy_list haben unterschiedliche Adressen

print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328

Elemente von original_list und copy_list haben die gleichen Adressen

print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440

Unterelemente von original_list und copy_list haben unterschiedliche Adressen

print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x24eef08 0x24f3300

Durch Ändern der Elemente von original_list werden die Elemente von copy_list NICHT geändert

original_list.append(6)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]

Durch Ändern von copy_list-Elementen werden original_list-Elemente NICHT geändert

copy_list.append(7)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]

Durch Ändern von original_list sub_elements werden die copy_list sub_elements NICHT geändert

original_list[5].append('c')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]

Durch Ändern von copy_list sub_elements werden original_list sub_elements NICHT geändert

copy_list[5].append('d')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'd'], 7]
Fouad Boukredine
quelle
0

Ich bin mir nicht sicher, ob es oben erwähnt wurde oder nicht, aber es ist sehr wichtig zu verstehen, dass .copy () einen Verweis auf das ursprüngliche Objekt erstellt. Wenn Sie das kopierte Objekt ändern, ändern Sie das ursprüngliche Objekt. .deepcopy () erstellt ein neues Objekt und kopiert das ursprüngliche Objekt in ein neues. Das Ändern eines neuen tief kopierten Objekts wirkt sich nicht auf das ursprüngliche Objekt aus.

Und ja, .deepcopy () kopiert das Originalobjekt rekursiv, während .copy () ein Referenzobjekt auf Daten der ersten Ebene des Originalobjekts erstellt.

Der Unterschied zwischen .copy () und .deepcopy () beim Kopieren / Referenzieren ist also signifikant.

remort
quelle
0

Deep Copy bezieht sich auf verschachtelte Strukturen. Wenn Sie eine Liste mit Listen haben, kopiert deepcopy auch die verschachtelten Listen, sodass es sich um eine rekursive Kopie handelt. Mit nur kopieren haben Sie eine neue äußere Liste, aber innere Listen sind Referenzen. Die Zuordnung wird nicht kopiert. Zum Beispiel

import copy
spam = [[0, 1, 2, 3], 4, 5]
cheese = copy.copy(spam)
cheese.append(3)
cheese[0].append(3)
print(spam)
print(cheese)

Ausgabe

[[0, 1, 2, 3, 3], 4, 5] [[0, 1, 2, 3, 3], 4, 5, 3] Kopiermethode Kopieren Sie den Inhalt der äußeren Liste in die neue Liste, aber die innere Liste ist Immer noch gleich für beide Listen. Wenn Sie also Änderungen an der inneren Liste von Listen vornehmen, wirkt sich dies auf beide Listen aus.

Wenn Sie jedoch Deep Copy verwenden, wird auch eine neue Instanz für die innere Liste erstellt.

import copy
spam = [[0, 1, 2, 3], 4, 5]
cheese = copy.deepcopy(spam)
cheese.append(3)
cheese[0].append(3)
print(spam)
print(cheese)

Ausgabe

[0, 1, 2, 3] [[0, 1, 2, 3, 3], 4, 5, 3]

Shubham Agarwal
quelle
-1
>>lst=[1,2,3,4,5]

>>a=lst

>>b=lst[:]

>>> b
[1, 2, 3, 4, 5]

>>> a
[1, 2, 3, 4, 5]

>>> lst is b
False

>>> lst is a
True

>>> id(lst)
46263192

>>> id(a)
46263192 ------>  See here id of a and id of lst is same so its called deep copy and even boolean answer is true

>>> id(b)
46263512 ------>  See here id of b and id of lst is not same so its called shallow copy and even boolean answer is false although output looks same.
Sudhir Tataraju
quelle
aist keine Deepcopy von lst!
Georgy