Ich setze dict2 = dict1
. Wenn ich dict2
bearbeite, ändert sich auch das Original dict1
. Warum?
>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2["key2"] = "WARUM?!"
>>> dict1
{'key2': 'WARUM?!', 'key1': 'value1'}
Ich setze dict2 = dict1
. Wenn ich dict2
bearbeite, ändert sich auch das Original dict1
. Warum?
>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2["key2"] = "WARUM?!"
>>> dict1
{'key2': 'WARUM?!', 'key1': 'value1'}
Python kopiert Objekte niemals implizit. Wenn Sie dict2 = dict1
setzen, machen Sie sie zu Referenzen auf dasselbe genaue Dictionary-Objekt, sodass, wenn Sie es verändern, alle Verweise darauf auf das Objekt in seinem aktuellen Zustand verweisen.
Wenn Sie das Dictionary kopieren möchten (was selten vorkommt), müssen Sie dies explizit tun mit
dict2 = dict(dict1)
oder
dict2 = dict1.copy()
Während dict.copy()
und dict(dict1)
eine Kopie erstellen, handelt es sich nur um flache Kopien. Wenn Sie eine tiefe Kopie wünschen, ist copy.deepcopy(dict1)
erforderlich. Ein Beispiel:
>>> source = {'a': 1, 'b': {'m': 4, 'n': 5, 'o': 6}, 'c': 3}
>>> copy1 = x.copy()
>>> copy2 = dict(x)
>>> import copy
>>> copy3 = copy.deepcopy(x)
>>> source['a'] = 10 # Eine Änderung an Eigenschaften der ersten Ebene wirkt sich nicht auf Kopien aus
>>> source
{'a': 10, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> copy1
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> copy2
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> copy3
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> source['b']['m'] = 40 # Eine Änderung an tiefen Eigenschaften WIRD die flache Kopie der Eigenschaft 'b.m' beeinflussen
>>> source
{'a': 10, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> copy1
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> copy2
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> copy3 # Die Eigenschaft 'b.m' der tiefen Kopie bleibt unverändert
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
In Bezug auf flache vs. tiefe Kopien, aus den Python copy
Moduldokumenten:
Der Unterschied zwischen flachen und tiefen Kopien ist nur relevant für zusammengesetzte Objekte (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 darauf ein, die auf die Objekte im Original gefunden wurden.
- Eine tiefe Kopie erstellt ein neues zusammengesetztes Objekt und fügt dann rekursiv Kopien davon ein, die auf die Objekte im Original gefunden wurden.
Im Detail und eine einfache Möglichkeit zu erinnern:
Immer wenn du dict2 = dict1 machst, bezieht sich dict2 auf dict1. Sowohl dict1 als auch dict2 zeigen auf denselben Speicherort im Speicher. Dies ist nur ein normaler Fall bei der Arbeit mit veränderlichen Objekten in Python. Wenn du mit veränderlichen Objekten in Python arbeitest, musst du vorsichtig sein, da es schwer zu debuggen ist.
Statt dict2 = dict1 zu verwenden, solltest du die Kopie (shallow copy)- und deepcopy-Methode aus dem copy-Modul von Python verwenden, um dict2 von dict1 zu trennen.
Der richtige Weg ist:
>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1.copy()
>>> dict2
{'key1': 'value1', 'key2': 'value2'}
>>> dict2["key2"] = "WARUM?"
>>> dict2
{'key1': 'value1', 'key2': 'WARUM?'}
>>> dict1
{'key1': 'value1', 'key2': 'value2'}
>>> id(dict1)
140641178056312
>>> id(dict2)
140641176198960
>>>
Wie du sehen kannst, ist die id von dict1 und dict2 unterschiedlich, was bedeutet, dass beide auf verschiedene Speicherorte im Speicher zeigen/referenzieren.
Diese Lösung funktioniert für Wörterbücher mit unveränderlichen Werten; dies ist nicht die richtige Lösung für solche mit veränderlichen Werten.
Zum Beispiel:
>>> import copy
>>> dict1 = {"key1" : "value1", "key2": {"mutable": True}}
>>> dict2 = dict1.copy()
>>> dict2
{'key1': 'value1', 'key2': {'mutable': True}}
>>> dict2["key2"]["mutable"] = False
>>> dict2
{'key1': 'value1', 'key2': {'mutable': False}}
>>> dict1
{'key1': 'value1', 'key2': {'mutable': False}}
>>> id(dict1)
140641197660704
>>> id(dict2)
140641196407832
>>> id(dict1["key2"])
140641176198960
>>> id(dict2["key2"])
140641176198960
Du siehst, dass obwohl wir eine Kopie für dict1 angewendet haben, der Wert von mutable sowohl in dict2 als auch in dict1 auf false geändert ist, obwohl wir es nur in dict2 geändert haben. Dies liegt daran, dass wir den Wert eines veränderlichen Wörterbuchteils von dict1 geändert haben. Wenn wir eine Kopie auf ein Wörterbuch anwenden, wird nur eine Shallow Copy durchgeführt, was bedeutet, dass es alle unveränderlichen Werte in ein neues Wörterbuch kopiert und nicht die veränderlichen Werte, sondern auf sie verweist.
Die ultimative Lösung besteht darin, eine Deepcopy von dict1 durchzuführen, um ein vollständig neues Wörterbuch mit allen kopierten Werten zu erstellen, einschließlich veränderlicher Werte.
>>>import copy
>>> dict1 = {"key1" : "value1", "key2": {"mutable": True}}
>>> dict2 = copy.deepcopy(dict1)
>>> dict2
{'key1': 'value1', 'key2': {'mutable': True}}
>>> id(dict1)
140641196228824
>>> id(dict2)
140641197662072
>>> id(dict1["key2"])
140641178056312
>>> id(dict2["key2"])
140641197662000
>>> dict2["key2"]["mutable"] = False
>>> dict2
{'key1': 'value1', 'key2': {'mutable': False}}
>>> dict1
{'key1': 'value1', 'key2': {'mutable': True}}
Wie du sehen kannst, sind die IDs unterschiedlich, das bedeutet, dass dict2 komplett ein neues Wörterbuch mit allen Werten in dict1 ist.
Deepcopy muss verwendet werden, wenn du immer einen der veränderlichen Werte ändern möchtest, ohne das Originalwörterbuch zu beeinflussen. Andernfalls kannst du eine Shallow Copy verwenden. Deepcopy ist langsam, da es rekursiv arbeitet, um alle verschachtelten Werte im Originalwörterbuch zu kopieren, und benötigt auch zusätzlichen Speicher.
Python 3.5+ bietet eine einfachere Möglichkeit, eine flache Kopie zu erstellen, indem der **-Operator verwendet wird. Definiert von Pep 448.
>>>dict1 = {"key1": "value1", "key2": "value2"}
>>>dict2 = {**dict1}
>>>print(dict2)
{'key1': 'value1', 'key2': 'value2'}
>>>dict2["key2"] = "WARUM?!"
>>>print(dict1)
{'key1': 'value1', 'key2': 'value2'}
>>>print(dict2)
{'key1': 'value1', 'key2': 'WARUM?!'}
** entpackt das Wörterbuch in ein neues Wörterbuch, das dann dict2 zugewiesen wird.
Wir können auch bestätigen, dass jedes Wörterbuch eine eindeutige id hat.
>>>id(dict1)
178192816
>>>id(dict2)
178192600
Wenn eine tiefe Kopie benötigt wird, ist copy.deepcopy() immer noch der richtige Weg.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.