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?
quelle
list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8] print(list_) print(newlist)
Dienewlist
Standbildanzeige[[1, 2], [3, 4]]
. Istlist_[0]
aber eine Liste, die veränderlich ist.list_[0]
ist veränderbar, aber Sie mutieren / modifizieren es nicht. Versuchen Sie eslist_[0].append(9)
oderlist_[0][0] = 7
stattdessen.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,
copies
kopieren 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.
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 wielist_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8]
und dienewlist
bleiben gleich. Handelt es sich bei der inneren Liste also um Referenzen?list_[0][0] = 7
Bei unveränderlichen Objekten ist das Erstellen einer Kopie wenig sinnvoll, da sie sich nicht ändern werden. Für veränderbare Objekte
assignment
,copy
unddeepcopy
verhält sich anders. Sprechen wir über jeden von ihnen mit Beispielen.Eine Zuweisungsoperation weist einfach die Referenz der Quelle dem Ziel zu, z.
Jetzt
i
undj
technisch bezieht sich auf die gleiche Liste. Beidei
undj
haben die gleiche Speicheradresse. Jede Aktualisierung eines der beiden wird auf den anderen übertragen. z.B:Auf der anderen Seite
copy
unddeepcopy
erstellt eine neue Kopie der Variablen. Änderungen an der ursprünglichen Variablen werden nun nicht mehr in die Kopiervariable übernommen und umgekehrt. Erstellen Siecopy(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
copy
unddeepcopy
:Beispiel für eine flache Liste mit
copy
:Beispiel für eine verschachtelte Liste mit
copy
:Beispiel für eine flache Liste mit
deepcopy
:Beispiel für eine verschachtelte Liste mit
deepcopy
:quelle
Lassen Sie uns in einem grafischen Beispiel sehen, wie der folgende Code ausgeführt wird:
quelle
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 wirdc
.c1=c
ist eine Zuweisung, die denselben Verweis auf dasselbe Objekt verwendet und diesen zuweistc1
. Da die Liste veränderbar ist, ist alles, was mit dieser Liste passiert, sichtbar, unabhängig davon, ob Sie überc
oder darauf zugreifenc1
, 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 zuweistc1
.c
zeigt immer noch auf die ursprüngliche Liste. Wenn Sie also die Liste unter ändern, ändert sich die Listec1
, auf die verwiesenc
wird, 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
a
undb
Ergebnis 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
e
und in diese kopierene1
, 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ürdene[0].append(3)
, danne
wäre es[[1, 2, 3],[4, 5, 6],[7, 8, 9]]
. Wäree1
aber auch so[[1, 2, 3],[4, 5, 6],[7, 8, 9]]
. Auf der anderen Seite, wenn Sie später tune.append([10, 11, 12])
,e
wäre[[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12]]
. abere1
noch[[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, danne
enthält drei Verweise auf die ursprünglichen drei Listen sowie einen weiteren Verweis auf eine neue Liste. Unde1
enthä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".
quelle
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:
und wir weisen dieser Liste eine andere Liste zu, wie:
Wenn wir dann list2 im Python-Terminal drucken, erhalten wir Folgendes:
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:
dann sind sowohl list1 als auch list2:
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:
Beachten Sie, dass list2 nicht betroffen ist. Wenn wir jedoch Änderungen an untergeordneten Objekten vornehmen, wie z.
dann werden sowohl list1 als auch list2 geändert:
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:
Beachten Sie, dass list2 nicht betroffen ist. Wenn wir jedoch Änderungen an untergeordneten Objekten vornehmen, wie z.
dann bleibt auch list2 unberührt, da alle untergeordneten Objekte und übergeordneten Objekte auf unterschiedliche Speicherorte verweisen:
Ich hoffe es hilft.
quelle
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.
quelle
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
copy
praktisch, da die ursprünglichen Listenelemente beim Ändern der Kopierelemente nicht geändert werden.Auf der anderen Seite hat
copy
dies auch einen "Nebeneffekt", wenn Sie eine Liste mit Listen (Unterlisten) haben und diesedeepcopy
lö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. Zudeepcopy
diesem Zweck verwenden Sie eine Lösung, die diesen "Nebeneffekt" beseitigt und eine Kopie erstellt, ohne den ursprünglichen Inhalt zu ändern.Das unterschiedliche Verhalten
copy
und die unterschiedlichendeep copy
Operationen 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:Lassen Sie uns nun einige
print
Tests durchführen und sehen, wie sich die ursprüngliche Liste im Vergleich zur Kopierliste verhält:original_list und copy_list haben unterschiedliche Adressen
Elemente von original_list und copy_list haben die gleichen Adressen
Unterelemente von original_list und copy_list haben die gleichen Adressen
Durch Ändern der Elemente von original_list werden die Elemente von copy_list NICHT geändert
Durch Ändern von copy_list-Elementen werden original_list-Elemente NICHT geändert
Ändern von original_list-Unterelementen Ändern Sie automatisch copy_list-Unterelemente
Ändern von copy_list-Unterelementen Ändern Sie automatisch original_list-Unterelemente
Zweite
Lassen Sie uns überprüfen, wie
deepcopy
wir uns verhalten, indem wir dasselbe tun wie beicopy
(Erstellen einer Originalliste und einer Kopie dieser Liste):Lassen Sie uns nun einige
print
Tests durchführen und sehen, wie sich die ursprüngliche Liste im Vergleich zur Kopierliste verhält:original_list und copy_list haben unterschiedliche Adressen
Elemente von original_list und copy_list haben die gleichen Adressen
Unterelemente von original_list und copy_list haben unterschiedliche Adressen
Durch Ändern der Elemente von original_list werden die Elemente von copy_list NICHT geändert
Durch Ändern von copy_list-Elementen werden original_list-Elemente NICHT geändert
Durch Ändern von original_list sub_elements werden die copy_list sub_elements NICHT geändert
Durch Ändern von copy_list sub_elements werden original_list sub_elements NICHT geändert
quelle
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.
quelle
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
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.
Ausgabe
[0, 1, 2, 3] [[0, 1, 2, 3, 3], 4, 5, 3]
quelle
quelle
a
ist keine Deepcopy vonlst
!