So kopieren Sie ein Wörterbuch und bearbeiten nur die Kopie

855

Kann mir bitte jemand das erklären? Das ergibt für mich keinen Sinn.

Ich kopiere ein Wörterbuch in ein anderes und bearbeite das zweite und beide werden geändert. Warum passiert dies?

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2
{'key2': 'value2', 'key1': 'value1'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key2': 'WHY?!', 'key1': 'value1'}
MadSc13ntist
quelle
4
PythonTutor eignet sich hervorragend zur Visualisierung von Python-Referenzen. Hier ist dieser Code im letzten Schritt . Sie können dasselbe Diktat sehen dict1und darauf dict2verweisen.
Wjandrea

Antworten:

883

Python kopiert niemals implizit Objekte. Wenn Sie festlegen dict2 = dict1, verweisen sie auf dasselbe exakte Diktierobjekt. Wenn Sie es also mutieren, beziehen sich alle Verweise darauf weiterhin auf das Objekt in seinem aktuellen Zustand.

Wenn Sie das Diktat kopieren möchten (was selten vorkommt), müssen Sie dies explizit mit tun

dict2 = dict(dict1)

oder

dict2 = dict1.copy()
Mike Graham
quelle
26
Es ist vielleicht besser zu sagen, "dict2 und dict1 zeigen auf dasselbe Wörterbuch". Sie ändern nicht dict1 oder dict2, sondern was sie zeigen.
GrayWizardx
276
Beachten Sie auch, dass dict.copy () flach ist. Wenn sich dort eine verschachtelte Liste / etc befindet, werden Änderungen auf beide angewendet. IIRC. Deepcopy wird das vermeiden.
Will
16
Es ist nicht ganz richtig, dass Python niemals implizit Objekte kopiert. Primitive Datentypen wie int, float und bool werden ebenfalls als Objekte behandelt (tun Sie dies einfach, um dies dir(1)zu sehen), aber sie werden implizit kopiert.
Daniel Kullmann
17
@danielkullmann, ich denke, Sie haben möglicherweise Missverständnisse über Python, basierend darauf, wie andere Sprachen, mit denen Sie umgegangen sind, funktionieren. In Python gibt es a) kein Konzept für "primitive Datentypen". int, floatUnd boolInstanzen sind echte Python - Objekte, und b) Objekte dieser Art wird nicht implizit kopiert , wenn Sie sie übergeben, nicht in einer semantischen Python - Ebene sicher und nicht einmal als Implementierungsdetail in CPython.
Mike Graham
39
Eine unbegründete Rhetorik wie "Deep Copy wird als schädlich angesehen" ist nicht hilfreich. Wenn alles andere gleich ist, führt das flache Kopieren einer komplexen Datenstruktur mit deutlich höherer Wahrscheinlichkeit zu unerwarteten Randfallproblemen als das tiefe Kopieren derselben Struktur. Eine Kopie, bei der Änderungen das Originalobjekt ändern, ist keine Kopie. Es ist ein Fehler. Ergo, die meisten Anwendungsfälle absolut sollte rufen copy.deepcopy()statt dict()oder dict.copy(). Imran ‚s kurze Antwort ist auf der rechten Seite der Vernunft, im Gegensatz zu dieser Antwort.
Cecil Curry
647

Wenn Sie zuweisen dict2 = dict1, erstellen Sie keine Kopie von dict1, es dict2ist nur ein anderer Name für dict1.

Verwenden Sie copy/ deepcopydes copyModuls , um die veränderlichen Typen wie Wörterbücher zu kopieren .

import copy

dict2 = copy.deepcopy(dict1)
Imran
quelle
80
Für jedes Wörterbuch, mit dem ich jemals arbeite, ist Deepcopy das, was ich brauche ... Ich habe nur einige Stunden aufgrund eines Fehlers verloren, weil ich keine vollständige Kopie eines verschachtelten Wörterbuchs erhalten habe und meine Änderungen an verschachtelten Einträgen das Original beeinflusst haben .
Flutefreak7
7
Hier gilt das gleiche. deepcopy () macht den Trick. Ich habe meine verschachtelten Diktate in einem rotierenden Cache durcheinander gebracht, indem ich einer 'Kopie' des ursprünglichen Ereignisses einen Zeitstempel hinzugefügt habe. Vielen Dank!
fxstein
8
Dies sollte eigentlich als die richtige Antwort markiert werden; Diese Antwort ist allgemein und funktioniert auch für ein Wörterbuch mit Wörterbüchern.
Orezvani
30
Dies sollte die akzeptierte Antwort sein. Die unbegründete Rhetorik "Deep Copy wird als schädlich angesehen", die im Kommentarbereich der aktuell akzeptierten Antwort enthalten ist, führt beim Kopieren verschachtelter Wörterbücher (wie die hier dokumentierten) offensichtlich zu Synchronisationsproblemen und sollte als solche in Frage gestellt werden.
Cecil Curry
Deepcopy ist der richtige Weg bei einer komplexen Wörterbuchstruktur. dict1.copy () kopiert einfach die Werte von Schlüsseln als Referenzen und nicht als Objekte.
Rohith N
182

Während dict.copy()und dict(dict1)generiert eine Kopie, sind sie nur flache Kopien. Wenn Sie eine tiefe Kopie wünschen , copy.deepcopy(dict1)ist 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  # a change to first-level properties won't affect copies
>>> 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  # a change to deep properties WILL affect shallow copies 'b.m' property
>>> 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  # Deep copy's 'b.m' property is unaffected
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}

In Bezug auf flache und tiefe Kopien aus den Dokumenten des Python- copyModuls :

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.
gpanda
quelle
2
Dies sollte die richtige Antwort sein, da das Diktat nicht explizit durchlaufen wird und für andere Primärstrukturen verwendet werden kann.
Nikkolasg
27
Nur um zu verdeutlichen: w=copy.deepcopy(x)ist die Schlüsselzeile.
Alkoholiday
Was ist der Unterschied zwischen dict2 = dict1und dict2 = copy.deepcopy(dict1)?
TheTank
1
@TheTank, y = x bewirkt, dass sich die beiden Namen (Referenzen) auf dasselbe Objekt beziehen, dh "y ist x" ist wahr. Jede Änderung, die durch x am Objekt vorgenommen wird, entspricht einer Änderung durch y. U, v, w sind jedoch Verweise auf neue verschiedene Objekte, deren Werte während der Instanziierung von x kopiert wurden. Die Unterschiede zwischen u, v (flache Kopie) und w (Deepcopy) finden Sie unter docs.python.org/2/library/copy.html
gpanda
63

Unter Python 3.5+ gibt es eine einfachere Möglichkeit, eine flache Kopie mit dem Operator ** Unpackaging zu erstellen. Definiert durch Pep 448 .

>>>dict1 = {"key1": "value1", "key2": "value2"}
>>>dict2 = {**dict1}
>>>print(dict2)
{'key1': 'value1', 'key2': 'value2'}
>>>dict2["key2"] = "WHY?!"
>>>print(dict1)
{'key1': 'value1', 'key2': 'value2'}
>>>print(dict2)
{'key1': 'value1', 'key2': 'WHY?!'}

** 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 eigene ID hat.

>>>id(dict1)
 178192816

>>>id(dict2)
 178192600

Wenn eine tiefe Kopie benötigt wird, ist copy.deepcopy () immer noch der richtige Weg.

PabTorre
quelle
3
Dies sieht schrecklich aus wie Zeiger in C ++. Schön, um die Aufgabe zu erfüllen, aber in Bezug auf die Lesbarkeit neige ich dazu, diese Art von Operatoren nicht zu mögen.
Ernesto
1
Es sieht zwar etwas schick aus ... aber wenn mehrere Wörterbücher zusammengeführt werden, sieht die Syntax ziemlich flüssig aus.
PabTorre
2
Seien Sie vorsichtig damit, es wird nur eine flache Kopie ausgeführt.
Sebastian Dressler
Sie haben Recht @SebastianDressler, ich werde Anpassungen vornehmen. Danke.
PabTorre
2
Nützlich, wenn Sie eine Kopie mit einigen Gewürzen erstellen möchten:dict2 = {**dict1, 'key3':'value3'}
evg656e
47

Die besten und einfachsten Möglichkeiten , eine Kopie eines Diktats in Python 2.7 und 3 zu erstellen, sind ...

So erstellen Sie eine Kopie eines einfachen (einstufigen) Wörterbuchs:

1. Verwenden Sie die dict () -Methode, anstatt eine Referenz zu generieren, die auf das vorhandene dict verweist.

my_dict1 = dict()
my_dict1["message"] = "Hello Python"
print(my_dict1)  # {'message':'Hello Python'}

my_dict2 = dict(my_dict1)
print(my_dict2)  # {'message':'Hello Python'}

# Made changes in my_dict1 
my_dict1["name"] = "Emrit"
print(my_dict1)  # {'message':'Hello Python', 'name' : 'Emrit'}
print(my_dict2)  # {'message':'Hello Python'}

2. Verwenden der integrierten update () -Methode des Python-Wörterbuchs.

my_dict2 = dict()
my_dict2.update(my_dict1)
print(my_dict2)  # {'message':'Hello Python'}

# Made changes in my_dict1 
my_dict1["name"] = "Emrit"
print(my_dict1)  # {'message':'Hello Python', 'name' : 'Emrit'}
print(my_dict2)  # {'message':'Hello Python'}

So erstellen Sie eine Kopie eines verschachtelten oder komplexen Wörterbuchs:

Verwenden Sie die integrierte in Kopie - Modul, das eine generische flache und tiefe Kopiervorgänge zur Verfügung stellt. Dieses Modul ist sowohl in Python 2.7 als auch in Python 3 vorhanden. *

import copy

my_dict2 = copy.deepcopy(my_dict1)
AKay Nirala
quelle
6
Ich glaube, es dict()entsteht eine flache Kopie, keine tiefe Kopie. Das heißt, wenn Sie ein verschachteltes haben, dictist das äußere dicteine Kopie, aber das innere Diktat ist ein Verweis auf das ursprüngliche innere Diktat.
Shmuels
@shmuels ja, beide Methoden erstellen eine flache Kopie, nicht die tiefe. Siehe die aktualisierte Antwort.
AKay Nirala
37

Sie können auch einfach ein neues Wörterbuch mit einem Wörterbuchverständnis erstellen. Dadurch wird das Importieren von Kopien vermieden.

dout = dict((k,v) for k,v in mydict.items())

Natürlich können Sie in Python> = 2.7 Folgendes tun:

dout = {k:v for k,v in mydict.items()}

Für die Abwärtskompatibilität ist die Top-Methode jedoch besser.

Stürzender Adam Hughes
quelle
4
Dies ist besonders nützlich, wenn Sie mehr Kontrolle darüber haben möchten, wie und was genau kopiert wird. +1
ApproachingDarknessFish
14
Beachten Sie, dass diese Methode keine tiefe Kopie ausführt. Wenn Sie eine flache Kopie wünschen, ohne die Kontrolle über die zu kopierenden Schlüssel zu haben, sind d2 = dict.copy(d1)auch keine Importe erforderlich.
Jarek Piórkowski
1
@ JarekPiórkowski: oder Sie können eine Methode wie eine Methode d2 = d1.copy()
aufrufen
Beachten Sie, dass Sie das Verständnis im ersten Beispiel nicht benötigen. dict.itemsgibt bereits ein iterierbares Schlüssel / Wert-Paar zurück. Sie können also einfach verwenden dict(mydict.items())(Sie können auch nur verwenden dict(mydict)). Es kann nützlich sein, das Verständnis zu haben, wenn Sie die Einträge filtern möchten.
Paul Rooney
22

Zusätzlich zu den anderen bereitgestellten Lösungen können Sie **das Wörterbuch in ein leeres Wörterbuch integrieren, z.

shallow_copy_of_other_dict = {**other_dict}.

Jetzt haben Sie eine "flache" Kopie von other_dict.

Auf Ihr Beispiel angewendet:

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = {**dict1}
>>> dict2
{'key1': 'value1', 'key2': 'value2'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key1': 'value1', 'key2': 'value2'}
>>>

Zeiger: Unterschied zwischen flachen und tiefen Kopien

d4rty
quelle
1
Dies führt zu einer flachen Kopie, nicht zu einer tiefen Kopie.
Sytech
1
Ich habe es versucht, aber Probleme gehabt. Dies funktioniert nur für Python 3.5 und höher. python.org/dev/peps/pep-0448
ThatGuyRob
19

Zuweisungsanweisungen in Python kopieren keine Objekte, sondern erstellen Bindungen zwischen einem Ziel und einem Objekt.

So dict2 = dict1ergibt sich eine weitere Bindung zwischen dict2und das Objekt , das dict1Bezug zu nehmen.

Wenn Sie ein Diktat kopieren möchten, können Sie das verwenden copy module. Das Kopiermodul hat zwei Schnittstellen:

copy.copy(x)
Return a shallow copy of x.

copy.deepcopy(x)
Return a deep copy of x.

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.

Zum Beispiel in Python 2.7.9:

>>> import copy
>>> a = [1,2,3,4,['a', 'b']]
>>> b = a
>>> c = copy.copy(a)
>>> d = copy.deepcopy(a)
>>> a.append(5)
>>> a[4].append('c')

und das Ergebnis ist:

>>> a
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> b
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> c
[1, 2, 3, 4, ['a', 'b', 'c']]
>>> d
[1, 2, 3, 4, ['a', 'b']]
lösen
quelle
10

Sie können die neu erstellte Kopie auf einmal kopieren und bearbeiten, indem Sie den dictKonstruktor mit zusätzlichen Schlüsselwortargumenten aufrufen :

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict(dict1, key2="WHY?!")
>>> dict1
{'key2': 'value2', 'key1': 'value1'}
>>> dict2
{'key2': 'WHY?!', 'key1': 'value1'}
Frerich Raabe
quelle
9

Das verwirrte mich anfangs auch, weil ich aus einem C-Hintergrund stammte.

In C ist eine Variable ein Speicherort mit einem definierten Typ. Durch Zuweisen zu einer Variablen werden die Daten in den Speicherort der Variablen kopiert.

In Python verhalten sich Variablen jedoch eher wie Zeiger auf Objekte. Wenn Sie also eine Variable einer anderen zuweisen, wird keine Kopie erstellt, sondern der Variablenname verweist nur auf dasselbe Objekt.

Craig McQueen
quelle
5
Python-Variablen verhalten sich eher wie C ++
Ruggero Turra
7
Weil alles in Python ein Objekt ist! diveintopython.net/getting_to_know_python/… (ja, diese Antwort ist viele Jahre zu spät, aber vielleicht ist sie für jemanden von Nutzen!)
grimman
1
Ich glaube, dass die Python-Sprachsemantik besagt, dass es keine "Variablen" gibt. Sie werden "benannte Referenzen" genannt; Dies bedeutet, dass der Verweis auf ein Objekt eine syntaktische Zeichenfolge im Code ist. Ein Objekt kann viele benannte Verweise darauf haben. Unveränderliche Objekte wie Ints und Floats sowie Str-Instanzen haben nur eine Instanz pro Prozess. Ein int von 1 im Speicher ändert sich nicht in eine 2 oder einen anderen Wert an derselben Speicheradresse, wenn Sie dies tun. Myvalue = 1 myvalue = 2
DevPlayer
7

Jede Variable in Python (Dinge wie dict1oder stroder __builtins__ist ein Zeiger auf ein verstecktes platonisches "Objekt" in der Maschine.

Wenn Sie festlegen dict1 = dict2, zeigen Sie einfach dict1auf dasselbe Objekt (oder denselben Speicherort oder eine beliebige Analogie) wie dict2. Das Objekt, auf das verwiesen wird, dict1ist dasselbe Objekt, auf das verwiesen wird dict2.

Sie können überprüfen: dict1 is dict2sollte sein True. Auch id(dict1)sollte das gleiche sein wie id(dict2).

Du willst dict1 = copy(dict2)oder dict1 = deepcopy(dict2).

Der Unterschied zwischen copyund deepcopy? deepcopywird sicherstellen, dass die Elemente von dict2(haben Sie es auf eine Liste gezeigt?) auch Kopien sind.

Ich benutze nicht deepcopyviel - es ist normalerweise eine schlechte Praxis, Code zu schreiben, der ihn benötigt (meiner Meinung nach).

wehmütig
quelle
Ich habe gerade festgestellt, dass ich immer Deepcopy verwenden muss, damit beim Kopieren eines verschachtelten Wörterbuchs und beim Ändern verschachtelter Einträge die Auswirkungen nur auf die Kopie und nicht auf das Original auftreten.
Flutefreak7
6

dict1ist ein Symbol, das auf ein zugrunde liegendes Wörterbuchobjekt verweist. Durch Zuweisen dict1zu wird dict2lediglich dieselbe Referenz zugewiesen . Durch Ändern des Werts eines Schlüssels über das dict2Symbol wird das zugrunde liegende Objekt geändert, was sich auch auswirkt dict1. Das ist verwirrend.

Es ist weitaus einfacher, über unveränderliche Werte als über Referenzen nachzudenken. Erstellen Sie daher nach Möglichkeit Kopien:

person = {'name': 'Mary', 'age': 25}
one_year_later = {**person, 'age': 26}  # does not mutate person dict

Dies ist syntaktisch dasselbe wie:

one_year_later = dict(person, age=26)
Petrus Theron
quelle
5

dict2 = dict1kopiert das Wörterbuch nicht. Es gibt dem Programmierer einfach eine zweite Möglichkeit ( dict2), auf dasselbe Wörterbuch zu verweisen.


quelle
5
>>> dict2 = dict1
# dict2 is bind to the same Dict object which binds to dict1, so if you modify dict2, you will modify the dict1

Es gibt viele Möglichkeiten, ein Dict-Objekt zu kopieren, das ich einfach benutze

dict_1 = {
           'a':1,
           'b':2
         }
dict_2 = {}
dict_2.update(dict_1)
imcaozi
quelle
12
dict_2 = dict_1.copy()ist viel effizienter und logischer.
Jean-François Fabre
2
Beachten Sie, dass, wenn Sie ein Diktat in dict1 haben, mit dict_1.copy () die Änderungen, die Sie am inneren Diktat in dict_2 vornehmen, auch auf das innere Diktat in dict_1 angewendet werden. In diesem Fall sollten Sie stattdessen copy.deepcopy (dict_1) verwenden.
Warteschlange
1

Wie andere erklärt haben, macht das eingebaute dictnicht das, was Sie wollen. In Python2 (und wahrscheinlich auch in 3) können Sie problemlos eine ValueDictKlasse erstellen , mit der kopiert wird, =sodass Sie sicher sein können, dass sich das Original nicht ändert.

class ValueDict(dict):

    def __ilshift__(self, args):
        result = ValueDict(self)
        if isinstance(args, dict):
            dict.update(result, args)
        else:
            dict.__setitem__(result, *args)
        return result # Pythonic LVALUE modification

    def __irshift__(self, args):
        result = ValueDict(self)
        dict.__delitem__(result, args)
        return result # Pythonic LVALUE modification

    def __setitem__(self, k, v):
        raise AttributeError, \
            "Use \"value_dict<<='%s', ...\" instead of \"d[%s] = ...\"" % (k,k)

    def __delitem__(self, k):
        raise AttributeError, \
            "Use \"value_dict>>='%s'\" instead of \"del d[%s]" % (k,k)

    def update(self, d2):
        raise AttributeError, \
            "Use \"value_dict<<=dict2\" instead of \"value_dict.update(dict2)\""


# test
d = ValueDict()

d <<='apples', 5
d <<='pears', 8
print "d =", d

e = d
e <<='bananas', 1
print "e =", e
print "d =", d

d >>='pears'
print "d =", d
d <<={'blueberries': 2, 'watermelons': 315}
print "d =", d
print "e =", e
print "e['bananas'] =", e['bananas']


# result
d = {'apples': 5, 'pears': 8}
e = {'apples': 5, 'pears': 8, 'bananas': 1}
d = {'apples': 5, 'pears': 8}
d = {'apples': 5}
d = {'watermelons': 315, 'blueberries': 2, 'apples': 5}
e = {'apples': 5, 'pears': 8, 'bananas': 1}
e['bananas'] = 1

# e[0]=3
# would give:
# AttributeError: Use "value_dict<<='0', ..." instead of "d[0] = ..."

Bitte beziehen Sie sich auf das hier beschriebene lvalue-Änderungsmuster: Python 2.7 - saubere Syntax für die lvalue-Änderung . Die wichtigste Beobachtung ist, dass strund intsich in Python als Werte verhalten (obwohl es sich tatsächlich um unveränderliche Objekte unter der Haube handelt). Während Sie das beobachten, beachten Sie bitte auch, dass nichts magisch Besonderes an stroder ist int. dictkann auf die gleiche Weise verwendet werden, und ich kann mir viele Fälle vorstellen, in denen ValueDictSinn macht.

personal_cloud
quelle
0

Der folgende Code befindet sich in Diktaten, die der JSON-Syntax mehr als dreimal schneller folgen als Deepcopy

def CopyDict(dSrc):
    try:
        return json.loads(json.dumps(dSrc))
    except Exception as e:
        Logger.warning("Can't copy dict the preferred way:"+str(dSrc))
        return deepcopy(dSrc)
Carsten Thielepape
quelle
0

Ich stieß auf ein eigenartiges Verhalten, als ich versuchte, die Wörterbuch-Eigenschaft der Klasse zu kopieren, ohne sie einer Variablen zuzuweisen

new = copy.deepcopy(my_class.a)funktioniert nicht dh modifizieren newmodifiziertmy_class.a

aber wenn Sie dies tun old = my_class.aund dann new = copy.deepcopy(old)funktioniert es perfekt, dh das Ändern newwirkt sich nicht ausmy_class.a

Ich bin mir nicht sicher, warum dies passiert, hoffe aber, dass es hilft, einige Stunden zu sparen! :) :)

Anushk
quelle
Wie macht man eine Deepcopy von my_class.a?
Anthony
Nicht der beste Weg. Gute Antwort ist unten.
David Beauchemin
-1

weil dict2 = dict1 ist, enthält dict2 den Verweis auf dict1. Sowohl dict1 als auch dict2 zeigen auf dieselbe Stelle im Speicher. Dies ist nur ein normaler Fall, wenn Sie mit veränderlichen Objekten in Python arbeiten. Wenn Sie mit veränderlichen Objekten in Python arbeiten, müssen Sie vorsichtig sein, da das Debuggen schwierig ist. Wie das folgende Beispiel.

 my_users = {
        'ids':[1,2],
        'blocked_ids':[5,6,7]
 }
 ids = my_users.get('ids')
 ids.extend(my_users.get('blocked_ids')) #all_ids
 print ids#output:[1, 2, 5, 6, 7]
 print my_users #output:{'blocked_ids': [5, 6, 7], 'ids': [1, 2, 5, 6, 7]}

In diesem Beispiel sollen alle Benutzer-IDs einschließlich blockierter IDs abgerufen werden. Das haben wir von der Variablen ids bekommen, aber wir haben auch den Wert von my_users unbeabsichtigt aktualisiert . Wenn Sie die IDs mit blockierten_IDs erweitert haben, wurden my_users aktualisiert, da sich die IDs auf my_users beziehen .

Vkreddy Komatireddy
quelle
-1

Kopieren mit einer for-Schleife:

orig = {"X2": 674.5, "X3": 245.0}

copy = {}
for key in orig:
    copy[key] = orig[key]

print(orig) # {'X2': 674.5, 'X3': 245.0}
print(copy) # {'X2': 674.5, 'X3': 245.0}
copy["X2"] = 808
print(orig) # {'X2': 674.5, 'X3': 245.0}
print(copy) # {'X2': 808, 'X3': 245.0}
Jesper Joachim Sørensen
quelle
1
Dies funktioniert nur für einfache Wörterbücher. Warum nicht verwenden deepcopy, das ausdrücklich für diesen Zweck gebaut wurde?
Anthony
Nicht der beste Weg. Gute Antwort ist unten.
David Beauchemin
-6

Sie können direkt verwenden:

dict2 = eval(repr(dict1))

Dabei ist das Objekt dict2 eine unabhängige Kopie von dict1, sodass Sie dict2 ändern können, ohne dict1 zu beeinflussen.

Dies funktioniert für jede Art von Objekt.

Viiik
quelle
4
Diese Antwort ist falsch und sollte nicht verwendet werden. Eine benutzerdefinierte Klasse verfügt beispielsweise möglicherweise nicht über eine geeignete Klasse, __repr__die durch eval rekonstruiert werden kann, und die Klasse des Objekts befindet sich möglicherweise nicht in dem aktuell aufzurufenden Bereich. Selbst wenn Sie sich an integrierte Typen halten, schlägt dies fehl, wenn dasselbe Objekt unter mehreren Schlüsseln gespeichert wird, da dict2dann zwei separate Objekte vorhanden wären. Ein selbstreferenzielles Wörterbuch, in dem es sich dict1selbst enthält, enthält stattdessen Ellipsis. Es wäre besser zu verwendendict1.copy()
Eldritch Cheese
Es wird nicht erwartet, dass Objekte (oder "Werte") immer eine getreue Darstellung durch Zeichenketten haben, jedenfalls nicht auf eine vom Menschen lesbare Weise.
Alexey