Warum aktualisiert das Aktualisieren des „flachen“ Kopierwörterbuchs nicht das „Original“-Wörterbuch? [duplicate]
Lesezeit: 5 Minuten
Benutzer225312
Beim Lesen der Dokumentation für dict.copy(), heißt es, dass es eine flache Kopie des Wörterbuchs erstellt. Gleiches gilt für das Buch, dem ich folge (Beazley’s Python Reference), in dem es heißt:
Die Methode m.copy() erstellt eine flache Kopie der in einem Zuordnungsobjekt enthaltenen Elemente und platziert sie in einem neuen Zuordnungsobjekt.
Bedenken Sie:
>>> original = dict(a=1, b=2)
>>> new = original.copy()
>>> new.update({'c': 3})
>>> original
{'a': 1, 'b': 2}
>>> new
{'a': 1, 'c': 3, 'b': 2}
Also nahm ich an, dass dies den Wert von aktualisieren würde original (und fügen Sie ‘c’ hinzu: 3), auch da ich eine flache Kopie gemacht habe. Wie, wenn Sie es für eine Liste tun:
>>> original = [1, 2, 3]
>>> new = original
>>> new.append(4)
>>> new, original
([1, 2, 3, 4], [1, 2, 3, 4])
Dies funktioniert wie erwartet.
Da beides flache Kopien sind, warum ist das der dict.copy() funktioniert nicht so wie ich es erwarte? Oder ist mein Verständnis von flachem und tiefem Kopieren fehlerhaft?
Kurios, dass sie “flach” nicht erklären. Insiderwissen, zwinker. Nur das Diktat und die Schlüssel sind eine Kopie, während verschachtelte Diktate innerhalb dieser ersten Ebene Referenzen sind und beispielsweise nicht in einer Schleife gelöscht werden können. Daher ist Pythons dict.copy() in diesem Fall weder nützlich noch intuitiv. Vielen Dank für Ihre Frage.
– gseattle
9. Juni 2017 um 10:34 Uhr
“Da beides seichte Kopien sind” – darum geht es hier. Das zweite Beispiel ist nicht eine Kopie, oberflächlich oder anderweitig.
– Karl Knechtel
26. März um 22:02 Uhr
kennytm
Mit “oberflächlichem Kopieren” ist das gemeint Inhalt des Wörterbuchs wird nicht nach Wert kopiert, sondern nur eine neue Referenz erstellt.
>>> a = {1: [1,2,3]}
>>> b = a.copy()
>>> a, b
({1: [1, 2, 3]}, {1: [1, 2, 3]})
>>> a[1].append(4)
>>> a, b
({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
Im Gegensatz dazu kopiert eine tiefe Kopie alle Inhalte nach Wert.
>>> import copy
>>> c = copy.deepcopy(a)
>>> a, c
({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
>>> a[1].append(5)
>>> a, c
({1: [1, 2, 3, 4, 5]}, {1: [1, 2, 3, 4]})
So:
b = a: Referenzzuordnung, Make a Und b zeigt auf dasselbe Objekt.
b = a.copy(): Flaches Kopieren, a Und b werden zu zwei isolierten Objekten, aber ihre Inhalte haben immer noch dieselbe Referenz
b = copy.deepcopy(a): Tiefes Kopieren, a Und bStruktur und Inhalt von werden vollständig isoliert.
Schöne Antwort, aber Sie könnten den Grammatikfehler in Ihrem ersten Satz korrigieren. Und es gibt keinen Grund, es nicht zu verwenden L wieder rein b. Dies würde das Beispiel vereinfachen.
– Tom Russel
27. Oktober 2017 um 4:47 Uhr
@kennytm: Was ist eigentlich der Unterschied zwischen den ersten beiden Beispielen? Sie erhalten dort das gleiche Ergebnis, aber eine etwas andere innere Umsetzung, aber worauf kommt es an?
– JavaSa
20. Januar 2018 um 11:53 Uhr
@JavaSa a[1] = {} wird beeinflussen b im ersten Beispiel und hat keinen Einfluss b im zweiten Beispiel.
– kennytm
22. Januar 2018 um 18:08 Uhr
Tolle Erklärung, … hat mir wirklich den Tag gerettet! Danke … Kann dies auch auf die Liste, Str und andere Datentypen von Python angewendet werden?
– Bhuro
19. Februar 2018 um 13:38 Uhr
@Sheldore dic_a Und dic_b beziehen sich auf dasselbe Wörterbuch, wenn Sie dic_b = dic_a. Die Zeichenfolgen im Wörterbuch sind unveränderlich, aber das ist irrelevant, weil dic_b['A'] = 'Adam' mutiert das Wörterbuch selbst.
– kennytm
20. September 2020 um 17:54 Uhr
Nehmen Sie dieses Beispiel:
original = dict(a=1, b=2, c=dict(d=4, e=5))
new = original.copy()
Lassen Sie uns nun einen Wert in der ‘flachen’ (ersten) Ebene ändern:
new['a'] = 10
# new = {'a': 10, 'b': 2, 'c': {'d': 4, 'e': 5}}
# original = {'a': 1, 'b': 2, 'c': {'d': 4, 'e': 5}}
# no change in original, since ['a'] is an immutable integer
Lassen Sie uns nun einen Wert eine Ebene tiefer ändern:
new['c']['d'] = 40
# new = {'a': 10, 'b': 2, 'c': {'d': 40, 'e': 5}}
# original = {'a': 1, 'b': 2, 'c': {'d': 40, 'e': 5}}
# new['c'] points to the same original['d'] mutable dictionary, so it will be changed
no change in original, since ['a'] is an immutable integer Das. Es beantwortet tatsächlich die gestellte Frage.
– CivFan
14. April 2015 um 18:08 Uhr
Es geht nicht um Deep Copy oder Shallow Copy, nichts von dem, was Sie tun, ist Deep Copy.
Hier:
>>> new = original
Sie erstellen einen neuen Verweis auf die Liste/das Diktat, auf das vom Original verwiesen wird.
während hier:
>>> new = original.copy()
>>> # or
>>> new = list(original) # dict(original)
Sie erstellen eine neue Liste/ein neues Diktat, das mit einer Kopie der Referenzen von Objekten gefüllt ist, die im ursprünglichen Container enthalten sind.
Stimmt, soweit es geht … aber es geht nicht weit genug, um die OP-Frage zu flach vs. tief zu beantworten.
– MarkHu
11. Februar 2021 um 2:02 Uhr
Vkreddy
Hinzufügen zu Kennytms Antwort. Wenn Sie eine flache Kopie machen parent.copy() Ein neues Wörterbuch wird mit denselben Schlüsseln erstellt, aber die Werte werden nicht kopiert, sondern referenziert. Wenn Sie einen neuen Wert hinzufügen parent_copy es wird nicht wirken Elternteil Weil parent_copy ist ein neues Wörterbuch, keine Referenz.
Der Hash(id)-Wert von Elternteil[1], parent_copy[1] sind identisch, was impliziert [1,2,3] von Elternteil[1] Und parent_copy[1] gespeichert unter der ID 140690938288400.
Aber Hasch von Elternteil Und parent_copy sind unterschiedlich, was impliziert, dass sie unterschiedliche Wörterbücher sind und parent_copy ist ein neues Wörterbuch mit Werten, die auf Werte von verweisen Elternteil
“neu” und “original” sind unterschiedliche Diktate, deshalb können Sie nur eines davon aktualisieren Artikel werden oberflächlich kopiert, nicht das Diktat selbst.
Stephan Rauch
In Ihrem zweiten Teil sollten Sie verwenden new = original.copy()
.copy Und = sind verschiedene Dinge.
Dschungeljäger
Inhalt sind oberflächlich kopiert.
Also wenn das Original dict enthält ein list oder ein anderes dictionarydas Ändern eines davon im Original oder seiner flachen Kopie ändert sie (die list oder der dict) in dem anderen.
14490000cookie-checkWarum aktualisiert das Aktualisieren des „flachen“ Kopierwörterbuchs nicht das „Original“-Wörterbuch? [duplicate]yes
Kurios, dass sie “flach” nicht erklären. Insiderwissen, zwinker. Nur das Diktat und die Schlüssel sind eine Kopie, während verschachtelte Diktate innerhalb dieser ersten Ebene Referenzen sind und beispielsweise nicht in einer Schleife gelöscht werden können. Daher ist Pythons dict.copy() in diesem Fall weder nützlich noch intuitiv. Vielen Dank für Ihre Frage.
– gseattle
9. Juni 2017 um 10:34 Uhr
“Da beides seichte Kopien sind” – darum geht es hier. Das zweite Beispiel ist nicht eine Kopie, oberflächlich oder anderweitig.
– Karl Knechtel
26. März um 22:02 Uhr