Jak skopiować słownik i edytować tylko kopię

855

Czy ktoś może mi to wyjaśnić? To nie ma dla mnie żadnego sensu.

Kopiuję słownik do innego i edytuję drugi i oba są zmieniane. Dlaczego to się dzieje?

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2
{'key2': 'value2', 'key1': 'value1'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key2': 'WHY?!', 'key1': 'value1'}
MadSc13ntist
źródło
4
PythonTutor doskonale nadaje się do wizualizacji odniesień do Pythona. Oto ten kod w ostatnim kroku . Możesz zobaczyć dict1i dict2wskazać ten sam słownik.
wjandrea,

Odpowiedzi:

883

Python nigdy niejawnie kopiuje obiekty. Po ustawieniu dict2 = dict1powoduje, że odnoszą się one do tego samego dokładnie obiektu dict, więc po zmutowaniu wszystkie odniesienia do niego będą odnosić się do obiektu w jego bieżącym stanie.

Jeśli chcesz skopiować dykt (co jest rzadkie), musisz to zrobić jawnie

dict2 = dict(dict1)

lub

dict2 = dict1.copy()
Mike Graham
źródło
26
Lepiej powiedzieć „dict2 i dict1 wskazują na ten sam słownik”, nie zmieniasz dict1 ani dict2, ale to, na co wskazują.
GrayWizardx,
275
Zauważ również, że dict.copy () jest płytkie, jeśli istnieje zagnieżdżona lista / etc tam zmiany zostaną zastosowane do obu. IIRC. Deepcopy pozwoli tego uniknąć.
Czy
16
Nie do końca jest prawdą, że python nigdy niejawnie kopiuje obiekty. Prymitywne typy danych, takie jak int, float i bool, są również traktowane jako obiekty (po prostu zrób to, dir(1)aby to zobaczyć), ale są domyślnie kopiowane.
Daniel Kullmann
17
@Danielkullmann, myślę, że możesz mieć nieporozumienia na temat Pythona w oparciu o to, w jaki sposób pracujesz w innych językach. W Pythonie: a) Nie ma pojęcia „prymitywnych typów danych”. int, floata boolinstancje są prawdziwymi obiektami Pythona, i b) obiekty tego typu nie są domyślnie kopiowane po ich przekazaniu, na pewno nie na poziomie semantycznym, a nawet jako szczegóły implementacji w CPython.
Mike Graham,
39
Nieuzasadniona retoryka, taka jak „Głęboka kopia jest uważana za szkodliwą”, nie jest pomocna. Wszystkie pozostałe elementy są równe, płytkie kopiowanie złożonej struktury danych znacznie zwiększa prawdopodobieństwo wystąpienia nieoczekiwanych problemów z przypadkowymi krawędziami niż głębokie kopiowanie tej samej struktury. Kopia, w której modyfikacje modyfikują oryginalny obiekt, nie jest kopią; to błąd. Ergo, większość przypadków użycia absolutnie powinna zadzwonić copy.deepcopy()zamiast dict()lub dict.copy(). Imran jest zwięzła odpowiedź znajduje się po prawej stronie rozsądku, w przeciwieństwie do tej odpowiedzi.
Cecil Curry,
646

Kiedy przypisujesz dict2 = dict1, nie tworzysz kopii dict1, skutkuje dict2to po prostu inną nazwą dla dict1.

Aby skopiować zmienne typów jak słowniki użytku copy/ deepcopyz copymodułu.

import copy

dict2 = copy.deepcopy(dict1)
Imran
źródło
80
W przypadku każdego słownika, z którym kiedykolwiek pracuję, potrzebuję głębokiej kopii ... Właśnie straciłem kilka godzin z powodu błędu, który był spowodowany tym, że nie otrzymałem pełnej kopii zagnieżdżonego słownika, a moje zmiany w zagnieżdżonych pozycjach miały wpływ na oryginał .
flutefreak7
7
To samo tutaj. deepcopy () załatwia sprawę. Zepsuło moje zagnieżdżone dykty w obrotowej pamięci podręcznej, dodając znacznik czasu do „kopii” oryginalnego zdarzenia. Dziękuję Ci!
fxstein
8
To właściwie powinno być oznaczone jako poprawna odpowiedź; Ta odpowiedź jest ogólna i działa również w przypadku słownika.
orezvani,
30
To powinna być zaakceptowana odpowiedź. Nieuzasadniona retoryka „Głęboka kopia jest uważana za szkodliwą” osadzona w sekcji komentarza obecnie przyjętej odpowiedzi rażąco zachęca do problemów z synchronizacją podczas kopiowania zagnieżdżonych słowników (takich jak te udokumentowane tutaj) i powinna zostać zakwestionowana jako taka.
Cecil Curry,
deepcopy to sposób, w jaki należy przejść w przypadku złożonej struktury słownika. dict1.copy () po prostu kopiuje wartości kluczy jako referencje, a nie jako obiekty.
Rohith N
182

Podczas gdy dict.copy()i dict(dict1)generuje kopię, są to tylko płytkie kopie. Jeśli potrzebujesz głębokiej kopii, copy.deepcopy(dict1)jest wymagana. Przykład:

>>> 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}}

Jeśli chodzi o płytkie i głębokie kopie, z dokumentacji modułu Pythoncopy :

Różnica między płytkim a głębokim kopiowaniem dotyczy tylko obiektów złożonych (obiektów zawierających inne obiekty, takich jak listy lub instancje klas):

  • Płytka kopia konstruuje nowy obiekt złożony, a następnie (w możliwym zakresie) wstawia do niego odwołania do obiektów znalezionych w oryginale.
  • Głęboka kopia konstruuje nowy obiekt złożony, a następnie rekurencyjnie wstawia do niego kopie obiektów znalezionych w oryginale.
gpanda
źródło
2
powinna to być właściwa odpowiedź, ponieważ nie pozwala ona na jawne zapętlenie dykta i może być używana do innych podstawowych struktur.
Nikkolasg
27
Wyjaśnij: w=copy.deepcopy(x)to kluczowa linia.
alkoholiday
Jaka jest różnica między dict2 = dict1i dict2 = copy.deepcopy(dict1)?
TheTank
1
@ Theank, y = x sprawia, że ​​dwie nazwy (odniesienia) odnoszą się do tego samego obiektu, tzn. „Y jest x” to Prawda. Każda zmiana dokonana na obiekcie przez x jest równoważna tej samej zmianie przez y. Jednak u, v, w są odwołaniami do nowych różnych obiektów, których wartości zostały skopiowane z x podczas tworzenia wystąpienia. Jeśli chodzi o różnice między u, v (płytka kopia) i w (deepcopy), sprawdź docs.python.org/2/library/copy.html
gpanda
63

W Pythonie 3.5+ istnieje łatwiejszy sposób na uzyskanie płytkiej kopii za pomocą ** operatora rozpakowywania. Zdefiniowany przez 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?!'}

** rozpakowuje słownik do nowego słownika, który jest następnie przypisywany do dict2.

Możemy również potwierdzić, że każdy słownik ma odrębny identyfikator.

>>>id(dict1)
 178192816

>>>id(dict2)
 178192600

Jeśli potrzebna jest głęboka kopia, to copy.deepcopy () jest nadal dobrym rozwiązaniem.

PabTorre
źródło
3
To wygląda okropnie jak wskaźniki w C ++. Miło za wykonanie zadania, ale jeśli chodzi o czytelność, nie lubię tego typu operatorów.
Ernesto,
1
Wygląda to trochę stylowo ... ale podczas łączenia wielu słowników, składnia wygląda całkiem gładko.
PabTorre
2
Uważaj z tym, wykonuje tylko płytką kopię.
Sebastian Dressler
masz rację @SebastianDressler, dokonam korekt. dzięki.
PabTorre
2
Przydatne, jeśli chcesz utworzyć kopię z niektórymi przyprawami:dict2 = {**dict1, 'key3':'value3'}
evg656e
47

Najlepszy i najprostszy sposób, aby utworzyć kopię o dict zarówno w Pythonie 2.7 i 3 są ...

Aby utworzyć kopię prostego (jednopoziomowego) słownika:

1. Za pomocą metody dict () zamiast generować odwołanie wskazujące na istniejący dykt.

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. Korzystanie z wbudowanej metody update () słownika python.

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'}

Aby utworzyć kopię zagnieżdżonego lub złożonego słownika:

Użyj wbudowanego modułu kopiowania , który zapewnia ogólne płytkie i głębokie operacje kopiowania. Ten moduł jest obecny zarówno w Pythonie 2.7, jak i 3. *

import copy

my_dict2 = copy.deepcopy(my_dict1)
AKay Nirala
źródło
6
Wierzę, że dict()tworzy płytką kopię, a nie głęboką kopię. Oznacza to, że jeśli masz zagnieżdżone, dictto zewnętrzny dictbędzie kopią, ale wewnętrzny dykt będzie odniesieniem do oryginalnego wewnętrznego dykt.
shmuels,
@shmuels tak, obie te metody utworzą płytką kopię, a nie głęboką. Zobacz zaktualizowaną odpowiedź.
AKay Nirala
37

Możesz także utworzyć nowy słownik ze zrozumieniem słownika. Pozwala to uniknąć importowania kopii.

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

Oczywiście w python> = 2.7 możesz zrobić:

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

Ale dla kompatybilności wstecznej najlepsza metoda jest lepsza.

Dashing Adam Hughes
źródło
4
Jest to szczególnie przydatne, jeśli chcesz mieć większą kontrolę nad tym, jak i co dokładnie jest kopiowane. +1
Zbliżanie
14
Zauważ, że ta metoda nie wykonuje głębokiej kopii, a jeśli chcesz mieć płytką kopię bez potrzeby kontrolowania kluczy, które chcesz skopiować, d2 = dict.copy(d1)nie wymaga to również żadnego importu.
Jarek Piórkowski
1
@ JarekPiórkowski: lub możesz wywołać metodę taką jak metoda:d2 = d1.copy()
Azat Ibrakov
Zauważ, że nie potrzebujesz zrozumienia w pierwszym przykładzie. dict.itemszwraca już iterowalną parę klucz / wartość. Więc możesz po prostu użyć dict(mydict.items())(możesz też po prostu użyć dict(mydict)). Przydatne może być zrozumienie, jeśli chcesz filtrować wpisy.
Paul Rooney
22

Oprócz innych dostarczonych rozwiązań można użyć **do zintegrowania słownika z pustym słownikiem, np.

shallow_copy_of_other_dict = {**other_dict}.

Teraz będziesz mieć „płytką” kopię other_dict.

Dotyczy twojego przykładu:

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

Wskaźnik: Różnica między płytkimi a głębokimi kopiami

d4rty
źródło
1
Powoduje to płytką kopię, a nie głęboką kopię.
sytech
1
Próbowałem tego, ale miałem problemy. Działa to tylko dla Pythona 3.5 i nowszych. python.org/dev/peps/pep-0448
ThatGuyRob
19

Instrukcje przypisania w Pythonie nie kopiują obiektów, tworzą powiązania między celem a obiektem.

Więc dict2 = dict1, wynika inny wiązania pomiędzy dict2i obiekt, który dict1odnosi się do.

jeśli chcesz skopiować nagranie, możesz użyć copy module. Moduł kopiowania ma dwa interfejsy:

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

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

Różnica między płytkim a głębokim kopiowaniem dotyczy tylko obiektów złożonych (obiektów zawierających inne obiekty, takich jak listy lub instancje klas):

Płytkie kopii tworzy nowy obiekt, a następnie związek (w zakresie możliwym) wkłada odniesień do niej na przedmioty znajdujące się w oryginale.

ZA Głęboka kopia konstruuje nowy obiekt związek, a następnie rekurencyjnie, wkładki do niego kopie obiektów znalezionych w oryginale.

Na przykład w 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')

a wynikiem jest:

>>> 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']]
poluzować
źródło
10

Możesz skopiować i edytować nowo utworzoną kopię za jednym razem, wywołując dictkonstruktor z dodatkowymi argumentami słów kluczowych:

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict(dict1, key2="WHY?!")
>>> dict1
{'key2': 'value2', 'key1': 'value1'}
>>> dict2
{'key2': 'WHY?!', 'key1': 'value1'}
Frerich Raabe
źródło
9

Początkowo to też mnie zdezorientowało, ponieważ pochodziłem z języka C.

W C zmienna jest lokalizacją w pamięci o zdefiniowanym typie. Przypisanie do zmiennej kopiuje dane do lokalizacji pamięci zmiennej.

Ale w Pythonie zmienne działają bardziej jak wskaźniki do obiektów. Zatem przypisanie jednej zmiennej do drugiej nie tworzy kopii, po prostu sprawia, że ​​nazwa zmiennej wskazuje na ten sam obiekt.

Craig McQueen
źródło
5
zmienne python działają bardziej jak odwołania do c ++
Ruggero Turra
7
Ponieważ wszystko w Pythonie jest przedmiotem! diveintopython.net/getting_to_know_python/... (tak, ta odpowiedź jest spóźniona o wiele lat, ale być może jest dla kogoś przydatna!)
grimman
1
Uważam, że semantyka języka Python mówi, że nie ma „zmiennych”. Nazywa się je „nazwanymi referencjami”; co oznacza, że ​​odwołanie do obiektu jest ciągiem składniowym w kodzie. Obiekt może mieć wiele nazwanych odniesień do niego. Niezmienne obiekty, takie jak inty, zmiennoprzecinkowe i instancje str, mają tylko jedną instancję na proces. Liczba 1 w pamięci nie zmienia się na 2 lub inną wartość pod tym samym adresem pamięci, gdy wykonujesz tę czynność moja wartość = 1 moja wartość = 2
DevPlayer
7

Każda zmienna w pythonie (rzeczy takie jak dict1lub strlub__builtins__ jest wskaźnikiem do jakiegoś ukrytego platońskiego „obiektu” wewnątrz maszyny.

Jeśli ustawisz dict1 = dict2, po prostu wskażesz dict1ten sam obiekt (lub lokalizację pamięci lub dowolną analogię), jak dict2. Teraz obiekt, do którego następuje odwołanie, dict1to ten sam obiekt, do którego odnosi siędict2 .

Możesz sprawdzić: dict1 is dict2powinno być True. Ponadto id(dict1)powinien być taki sam jakid(dict2) .

Chcesz dict1 = copy(dict2)lubdict1 = deepcopy(dict2) .

Różnica między copyi deepcopy? deepcopyupewni się, że elementydict2 (czy wskazałeś na listę?) są również kopiami.

Nie używam deepcopydużo - zwykle słabą praktyką jest pisanie kodu, który tego wymaga (moim zdaniem).

mglisty
źródło
Właśnie zdałem sobie sprawę, że zawsze muszę używać głębokiej kopii, aby po skopiowaniu zagnieżdżonego słownika i rozpoczęciu modyfikowania zagnieżdżonych wpisów efekty występowały tylko na kopii, a nie na oryginale.
flutefreak7
6

dict1jest symbolem, który odwołuje się do podstawowego obiektu słownika. Przypisanie dict1do dict2jedynie przypisania tego samego odwołania. Zmiana wartości klucza za pomocą dict2symbolu zmienia podstawowy obiekt, co również ma wpływ dict1. To jest mylące.

O wiele łatwiej jest wnioskować o niezmiennych wartościach niż referencjach, więc rób kopie, gdy tylko jest to możliwe:

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

Jest to składniowo to samo, co:

one_year_later = dict(person, age=26)
Petrus Theron
źródło
5

dict2 = dict1nie kopiuje słownika. To po prostu daje programiście drugi sposób ( dict2) na odniesienie do tego samego słownika.


źródło
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

Istnieje wiele sposobów kopiowania obiektu Dict, po prostu używam

dict_1 = {
           'a':1,
           'b':2
         }
dict_2 = {}
dict_2.update(dict_1)
imcaozi
źródło
12
dict_2 = dict_1.copy()jest znacznie bardziej wydajny i logiczny.
Jean-François Fabre
2
Zauważ, że jeśli masz dyk wewnątrz dict1, za pomocą dict_1.copy () zmiany, które wprowadzasz w wewnętrznym dykcie w dict_2, są również stosowane do wewnętrznego dykta w dict_1. W takim przypadku należy zamiast tego użyć copy.deepcopy (dict_1).
queise
1

Jak wyjaśnili inni, wbudowane narzędzie dictnie robi tego, co chcesz. Ale w Python2 (i prawdopodobnie również 3) możesz łatwo utworzyć ValueDictklasę, z =którą będziesz kopiować, aby mieć pewność, że oryginał się nie zmieni.

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] = ..."

Proszę odnieść się do omawianego tutaj wzoru modyfikacji wartości: Python 2.7 - czysta składnia dla modyfikacji wartości . Kluczem jest to, że obserwacja stri intzachowywać się jak wartości w Pythonie (choć są one rzeczywiście niezmienne obiekty pod maską). Obserwując to, zauważ również, że nic nie jest magicznie wyjątkowe w strlub int. dictmogą być używane w ten sam sposób i mogę myśleć o wielu przypadkach, w których ValueDictma to sens.

personal_cloud
źródło
0

poniższy kod, który jest na dyktando, który postępuje zgodnie ze składnią Json ponad 3 razy szybciej niż 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
źródło
0

natknąłem się na szczególne zachowanie podczas próby głębokiego skopiowania właściwości słownika klasy bez przypisywania jej do zmiennej

new = copy.deepcopy(my_class.a)nie działa, tj. modyfikowanie newmodyfikacjimy_class.a

ale jeśli to zrobisz, old = my_class.aa następnie new = copy.deepcopy(old)zadziała to idealnie, tj. modyfikacja newnie ma wpływumy_class.a

Nie jestem pewien, dlaczego tak się dzieje, ale mam nadzieję, że pomoże to zaoszczędzić kilka godzin! :)

Anushk
źródło
Jak więc wykonać kopię my_class.a?
Anthony
Nie najlepszy sposób. Dobra odpowiedź jest poniżej.
David Beauchemin
-1

ponieważ dict2 = dict1, dict2 zawiera odniesienie do dict1. Zarówno dict1, jak i dict2 wskazują to samo miejsce w pamięci. Jest to normalny przypadek podczas pracy ze zmiennymi obiektami w Pythonie. Podczas pracy ze zmiennymi obiektami w Pythonie musisz być ostrożny, ponieważ trudno jest debugować. Tak jak w poniższym przykładzie.

 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]}

Ten przykładowy zamiar polega na uzyskaniu wszystkich identyfikatorów użytkowników, w tym identyfikatorów zablokowanych. Otrzymaliśmy to ze zmiennej ids, ale również przypadkowo zaktualizowaliśmy wartość my_users . kiedy rozszerzyłeś identyfikatory za pomocą block_ids, my_users zostali zaktualizowani, ponieważ identyfikatory odnoszą się do my_users .

Vkreddy Komatireddy
źródło
-1

Kopiowanie przy użyciu pętli for:

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
źródło
1
Działa to tylko w przypadku prostych słowników. Dlaczego nie skorzystać deepcopy, który jest zbudowany specjalnie do tego celu?
Anthony
Nie najlepszy sposób. Dobra odpowiedź jest poniżej.
David Beauchemin
-6

Możesz użyć bezpośrednio:

dict2 = eval(repr(dict1))

gdzie obiekt dict2 jest niezależną kopią dict1, więc możesz modyfikować dict2 bez wpływu na dict1.

Działa to dla każdego rodzaju obiektu.

Viiik
źródło
4
Ta odpowiedź jest niepoprawna i nie należy jej używać. Na przykład klasa zdefiniowana przez użytkownika może nie mieć odpowiedniego __repr__do odtworzenia przez eval, ani klasa obiektu nie może być w bieżącym zakresie, który ma zostać wywołany. Nawet trzymanie się wbudowanych typów, to się nie powiedzie, jeśli ten sam obiekt jest przechowywany pod wieloma kluczami, tak jak dict2wtedy, gdyby miały dwa oddzielne obiekty. dict1Zamiast tego będzie zawierał samoreferencyjny słownik, w którym się zawiera Ellipsis. Lepiej byłoby użyćdict1.copy()
Eldritch Cheese
Nie oczekuje się, że obiekty (lub „wartości”) zawsze będą wiernie reprezentowane przez ciągi znaków, a nie w zwykły sposób czytelny dla człowieka.
Alexey