Cara menyalin kamus dan hanya mengedit salinannya

856

Bisakah seseorang tolong jelaskan hal ini kepada saya? Ini tidak masuk akal bagi saya.

Saya menyalin kamus ke kamus lain dan mengedit kamus kedua dan keduanya diubah. Mengapa ini terjadi?

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2
{'key2': 'value2', 'key1': 'value1'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key2': 'WHY?!', 'key1': 'value1'}
MadSc13ntist
sumber
4
PythonTutor sangat bagus untuk memvisualisasikan referensi Python. Inilah kode ini pada langkah terakhir . Anda dapat melihat dict1dan dict2menunjuk ke dikt yang sama.
wjandrea

Jawaban:

883

Python tidak pernah secara implisit menyalin objek. Ketika Anda mengatur dict2 = dict1, Anda membuat mereka merujuk ke objek dict yang sama persis, jadi ketika Anda memutasikannya, semua referensi padanya tetap merujuk ke objek dalam keadaan saat ini.

Jika Anda ingin menyalin dikt (yang jarang), Anda harus melakukannya secara eksplisit

dict2 = dict(dict1)

atau

dict2 = dict1.copy()
Mike Graham
sumber
26
Mungkin lebih baik untuk mengatakan "titik dict2 dan dict1 ke kamus yang sama ", Anda tidak mengubah dict1 atau dict2 tetapi apa yang mereka tunjukkan.
GrayWizardx
276
Juga catat bahwa dict.copy () dangkal, jika ada daftar bertingkat / etc di sana perubahan akan diterapkan untuk keduanya. IIRC. Deepcopy akan menghindarinya.
Will
16
Tidak sepenuhnya benar bahwa python tidak pernah secara implisit menyalin objek. Tipe data primitif, seperti int, float, dan bool, juga diperlakukan sebagai objek (lakukan saja dir(1)untuk melihat itu), tetapi mereka disalin secara implisit.
daniel kullmann
17
@danielkullmann, saya pikir Anda mungkin memiliki kesalahpahaman tentang Python berdasarkan pada bagaimana bahasa lain yang Anda gunakan bekerja. Dalam Python, a) Tidak ada konsep "tipe data primitif". int,, floatdan boolinstance adalah objek Python sungguhan, dan b) objek jenis ini tidak disalin secara implisit ketika Anda melewatinya, tidak pada level semantik Python pasti dan bahkan tidak sebagai detail implementasi dalam CPython.
Mike Graham
39
Retorika tidak berdasar seperti "Salinan dalam dianggap berbahaya" tidak membantu. Semua yang lain sama, menyalin dangkal struktur data yang kompleks secara signifikan lebih cenderung menghasilkan masalah tepi kasus yang tidak terduga daripada menyalin dalam struktur yang sama. Salinan di mana modifikasi memodifikasi objek asli bukan salinan; itu adalah bug. Ergo, kebanyakan kasus penggunaan benar - benar harus memanggil copy.deepcopy()daripada dict()atau dict.copy(). Imran 's jawaban singkat adalah di sisi kanan kewarasan, tidak seperti jawaban ini.
Cecil Curry
647

Ketika Anda menetapkan dict2 = dict1 , Anda tidak membuat salinan dict1, itu dict2hanya menjadi nama lain untuk dict1.

Untuk menyalin tipe yang bisa berubah-ubah seperti kamus, gunakan copy/ deepcopydari copymodul.

import copy

dict2 = copy.deepcopy(dict1)
Imran
sumber
80
Untuk kamus apa pun yang pernah saya kerjakan, deepcopy adalah apa yang saya butuhkan ... Saya baru saja kehilangan beberapa jam karena bug yang disebabkan karena saya tidak mendapatkan salinan lengkap kamus bersarang dan perubahan saya ke entri bersarang mempengaruhi yang asli .
flutefreak7
7
Sama disini. deepcopy () melakukan trik. Mengacaukan dict saya yang bersarang di dalam cache yang berputar dengan menambahkan stempel waktu ke 'salinan' acara asli. Terima kasih!
fxstein
8
Ini sebenarnya harus ditandai sebagai jawaban yang benar; Jawaban ini bersifat umum dan juga berfungsi untuk kamus kamus.
orezvani
30
Ini harus menjadi jawaban yang diterima. Retorika "Deep copy dianggap berbahaya" retorika tertanam di bagian komentar dari jawaban yang diterima saat ini secara terang-terangan mengundang kesengsaraan sinkronisasi ketika menyalin kamus bersarang (seperti yang didokumentasikan di sini) dan harus ditantang seperti itu.
Cecil Curry
deepcopy adalah cara untuk pergi dalam kasus struktur kamus yang kompleks. dict1.copy () cukup menyalin nilai kunci sebagai referensi dan bukan sebagai objek.
Rohith N
182

Sementara dict.copy()dan dict(dict1)menghasilkan salinan, mereka hanya salinan dangkal . Jika Anda ingin salinan yang dalam , copy.deepcopy(dict1)diperlukan. Sebuah contoh:

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

Mengenai salinan dangkal vs dalam, dari modul Python copydocs :

Perbedaan antara penyalinan dangkal dan dalam hanya relevan untuk objek majemuk (objek yang berisi objek lain, seperti daftar atau instance kelas):

  • Salinan dangkal membangun objek majemuk baru dan kemudian (sejauh mungkin) menyisipkan referensi ke objek yang ditemukan dalam aslinya.
  • Salinan dalam membangun objek majemuk baru dan kemudian, secara rekursif, menyisipkan salinan ke dalamnya objek yang ditemukan dalam aslinya.
gpanda
sumber
2
ini harus menjadi jawaban yang tepat karena tidak secara eksplisit mengulangi dikt dan dapat digunakan untuk struktur utama lainnya.
Nikkolasg
27
Hanya untuk memperjelas: w=copy.deepcopy(x)adalah kunci utama.
alcoholiday
Apa perbedaan antara dict2 = dict1dan dict2 = copy.deepcopy(dict1)?
TheTank
1
@TheTank, y = x membuat dua nama (referensi) merujuk ke objek yang sama, yaitu "y is x" adalah True. Setiap perubahan yang dilakukan pada objek melalui x sama dengan perubahan yang sama melalui y. Namun u, v, w adalah referensi ke objek baru yang berbeda yang memiliki nilai yang disalin dari x selama instantiasi. Adapun perbedaan antara u, v (salinan dangkal) dan w (deepcopy), silakan periksa docs.python.org/2/library/copy.html
gpanda
63

Pada python 3.5+ ada cara yang lebih mudah untuk mendapatkan salinan yang dangkal dengan menggunakan operator pembungkusan **. Didefinisikan oleh 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?!'}

** membongkar kamus ke kamus baru yang kemudian ditugaskan ke dict2.

Kami juga dapat mengonfirmasi bahwa setiap kamus memiliki id berbeda.

>>>id(dict1)
 178192816

>>>id(dict2)
 178192600

Jika salinan yang dalam diperlukan, maka copy.deepcopy () masih merupakan cara yang harus dilakukan.

PabTorre
sumber
3
Ini sangat mirip petunjuk di C ++. Bagus untuk menyelesaikan tugas, tetapi mudah dibaca, saya cenderung tidak menyukai jenis operator ini.
Ernesto
1
Memang memiliki semacam tampilan c'ish ... tetapi ketika menggabungkan bersama beberapa kamus, sintaks memang terlihat cukup mulus.
PabTorre
2
Hati-hati dengan itu, ia hanya melakukan salinan dangkal.
Sebastian Dressler
Anda benar @SebastianDressler, saya akan membuat penyesuaian. thnx.
PabTorre
2
Berguna jika Anda ingin membuat salinan dengan beberapa spicies:dict2 = {**dict1, 'key3':'value3'}
evg656e
48

Yang terbaik dan cara termudah untuk membuat salinan dari dict di kedua Python 2,7 dan 3 yang ...

Untuk membuat salinan kamus sederhana (level tunggal):

1. Menggunakan metode dict () , alih-alih menghasilkan referensi yang menunjuk ke dict yang ada.

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. Menggunakan metode pemutakhiran () kamus python bawaan.

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

Untuk membuat salinan kamus bersarang atau kompleks:

Gunakan modul salin internal , yang menyediakan operasi salin dangkal dan dalam generik. Modul ini hadir dalam Python 2.7 dan 3. *

import copy

my_dict2 = copy.deepcopy(my_dict1)
AKay Nirala
sumber
6
Saya percaya dict()menciptakan salinan dangkal bukan salinan dalam. Berarti bahwa jika Anda memiliki sarang dictmaka bagian luar dictakan menjadi salinan tetapi bagian dalam akan menjadi referensi ke bagian dalam yang asli.
shmuels
@shmuels ya, kedua metode ini akan membuat salinan yang dangkal, bukan yang dalam. Lihat, jawaban yang diperbarui.
AKay Nirala
37

Anda juga bisa membuat kamus baru dengan pemahaman kamus. Ini menghindari mengimpor salinan.

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

Tentu saja dengan python> = 2.7 yang dapat Anda lakukan:

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

Tetapi untuk compat mundur., Metode teratas lebih baik.

Gagah Adam Hughes
sumber
4
Ini sangat berguna jika Anda ingin lebih banyak kontrol atas bagaimana dan apa yang sebenarnya disalin. +1
ApproachingDarknessFish
14
Perhatikan bahwa metode ini tidak melakukan salinan yang dalam, dan jika Anda ingin salinan yang dangkal tanpa perlu mengontrol kunci yang akan disalin, d2 = dict.copy(d1)tidak memerlukan impor apa pun.
Jarek Piórkowski
1
@ JarekPiórkowski: atau Anda dapat memanggil metode seperti metode:d2 = d1.copy()
Azat Ibrakov
Perhatikan bahwa Anda tidak perlu pemahaman dalam contoh pertama. dict.itemssudah mengembalikan pasangan kunci / nilai iterable. Jadi Anda bisa menggunakan dict(mydict.items())(Anda juga bisa menggunakan dict(mydict)). Mungkin bermanfaat untuk memiliki pemahaman jika Anda ingin memfilter entri.
Paul Rooney
22

Selain solusi lain yang disediakan, Anda dapat menggunakan **untuk mengintegrasikan kamus ke dalam kamus kosong, misalnya,

shallow_copy_of_other_dict = {**other_dict}.

Sekarang Anda akan memiliki salinan "dangkal" other_dict .

Diterapkan pada contoh Anda:

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

Pointer: Perbedaan antara copys dangkal dan dalam

d4rty
sumber
1
Ini menghasilkan salinan yang dangkal, bukan salinan yang dalam.
sytech
1
Saya mencoba ini tetapi mengalami masalah. Ini hanya berfungsi untuk python 3.5 dan lebih tinggi. python.org/dev/peps/pep-0448
ThatGuyRob
19

Pernyataan penugasan dalam Python tidak menyalin objek, mereka membuat ikatan antara target dan objek.

jadi,, dict2 = dict1itu menghasilkan pengikatan lain antara dict2dan objek itudict1 merujuk.

jika Anda ingin menyalin sebuah dikt, Anda dapat menggunakan copy module. Modul salin memiliki dua antarmuka:

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

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

Perbedaan antara penyalinan dangkal dan dalam hanya relevan untuk objek majemuk (objek yang berisi objek lain, seperti daftar atau instance kelas):

Sebuah salinan dangkal membangun sebuah objek senyawa baru dan kemudian (sejauh mungkin) memasukkan referensi ke dalamnya untuk benda yang ditemukan dalam bahasa aslinya.

Sebuah salinan dalam membangun sebuah objek senyawa baru dan kemudian, secara rekursif, menyisipkan salinan ke dalamnya benda-benda yang ditemukan di aslinya.

Misalnya, dalam 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')

dan hasilnya adalah:

>>> 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']]
melonggarkan
sumber
10

Anda dapat menyalin dan mengedit salinan yang baru dibuat dalam sekali jalan dengan memanggil dictkonstruktor dengan argumen kata kunci tambahan:

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

Ini membingungkan saya juga, pada awalnya, karena saya berasal dari latar belakang C.

Dalam C, variabel adalah lokasi di memori dengan tipe yang ditentukan. Menetapkan ke variabel menyalin data ke lokasi memori variabel.

Tetapi dalam Python, variabel bertindak lebih seperti pointer ke objek. Jadi menugaskan satu variabel ke variabel lain tidak membuat salinan, itu hanya membuat nama variabel menunjuk ke objek yang sama.

Craig McQueen
sumber
5
variabel python bertindak lebih seperti referensi c ++
Ruggero Turra
7
Karena semua yang ada di Python adalah objek! diveintopython.net/getting_to_know_python/… (ya, respons ini terlambat bertahun-tahun, tapi mungkin itu berguna bagi seseorang!)
grimman
1
Saya percaya bahwa semantik bahasa Python mengatakan tidak ada "variabel". Mereka disebut "referensi bernama"; artinya referensi ke suatu objek adalah string sintaksis dalam kode. Suatu objek dapat memiliki banyak referensi bernama untuk itu. Objek yang tidak dapat diubah seperti int dan floats dan str instance hanya memiliki satu instance per proses. Int 1 dalam memori tidak berubah menjadi 2 atau beberapa nilai lain pada alamat memori yang sama ketika Anda melakukan ini myvalue = 1 myvalue = 2
DevPlayer
7

Setiap variabel dalam python (hal-hal seperti dict1atau stratau __builtins__adalah pointer ke beberapa "objek" platonis tersembunyi di dalam mesin.

Jika Anda mengatur dict1 = dict2, Anda hanya menunjuk dict1ke objek yang sama (atau lokasi memori, atau analogi apa pun yang Anda suka) dict2. Sekarang, objek yang dirujuk oleh dict1adalah objek yang sama yang dirujuk oleh dict2.

Anda dapat memeriksa: dict1 is dict2seharusnya True. Juga, id(dict1)harus sama denganid(dict2) .

Anda mau dict1 = copy(dict2), ataudict1 = deepcopy(dict2) .

Perbedaan antara copydan deepcopy? deepcopyakan memastikan bahwa elemendict2 (apakah Anda mengarahkannya pada daftar?) juga merupakan salinan.

Saya tidak menggunakan deepcopybanyak - biasanya praktik buruk untuk menulis kode yang membutuhkannya (menurut saya).

sayu
sumber
Saya baru sadar saya harus selalu menggunakan deepcopy sehingga ketika saya menyalin kamus bersarang dan mulai memodifikasi entri bersarang, efeknya hanya terjadi pada salinan dan bukan yang asli.
flutefreak7
6

dict1adalah simbol yang merujuk objek kamus yang mendasarinya. Menugaskan dict1untuk dict2hanya memberikan referensi yang sama. Mengubah nilai kunci melalui dict2simbol akan mengubah objek yang mendasarinya, yang juga memengaruhidict1 . Ini membingungkan.

Jauh lebih mudah untuk beralasan tentang nilai-nilai yang tidak dapat diubah daripada referensi, jadi buatlah salinan bila memungkinkan:

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

Secara sintaksis sama dengan:

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

dict2 = dict1tidak menyalin kamus. Ini hanya memberi Anda programmer cara kedua ( dict2) untuk merujuk ke kamus yang sama.


sumber
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

Ada banyak cara untuk menyalin objek Dict, saya hanya menggunakan

dict_1 = {
           'a':1,
           'b':2
         }
dict_2 = {}
dict_2.update(dict_1)
imcaozi
sumber
12
dict_2 = dict_1.copy()jauh lebih efisien dan logis.
Jean-François Fabre
2
Perhatikan bahwa jika Anda memiliki dict dict1, dengan dict_1.copy () perubahan yang Anda lakukan pada dict dalam dict_2 juga diterapkan ke dict dalam dict_1. Dalam hal ini Anda harus menggunakan copy.deepcopy (dict_1) sebagai gantinya.
antri
1

Seperti yang dijelaskan orang lain, built-in dicttidak melakukan apa yang Anda inginkan. Tetapi dalam Python2 (dan mungkin 3 juga) Anda dapat dengan mudah membuat ValueDictkelas yang menyalin =sehingga Anda dapat yakin bahwa yang asli tidak akan berubah.

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

Lihat pola modifikasi nilai yang dibahas di sini: Python 2.7 - sintaksis bersih untuk modifikasi nilai . Pengamatan utama adalah itu strdan intberperilaku sebagai nilai-nilai dalam Python (meskipun mereka sebenarnya benda abadi di bawah tenda). Saat Anda mengamati itu, harap perhatikan juga bahwa tidak ada yang istimewa stratau ajaib int. dictdapat digunakan dalam banyak cara yang sama, dan saya bisa memikirkan banyak kasus di mana ValueDictmasuk akal.

personal_cloud
sumber
0

kode berikut, yaitu pada dikt yang mengikuti sintaks json lebih dari 3 kali lebih cepat dari 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
sumber
0

saya berlari ke perilaku aneh ketika mencoba untuk mendalami properti kamus dari kelas tanpa menetapkannya ke variabel

new = copy.deepcopy(my_class.a)tidak berfungsi yaitu memodifikasi newmemodifikasimy_class.a

tetapi jika Anda melakukannya old = my_class.adan new = copy.deepcopy(old)berfungsi dengan baik yaitu memodifikasi newtidak mempengaruhimy_class.a

Saya tidak yakin mengapa ini terjadi, tetapi saya harap ini bisa menghemat waktu! :)

Anushk
sumber
Jadi bagaimana Anda membuat deepcopy my_class.a?
Anthony
Bukan cara terbaik. Respons yang baik di bawah.
David Beauchemin
-1

karena, dict2 = dict1, dict2 memegang referensi ke dict1. Kedua dict1 dan dict2 menunjuk ke lokasi yang sama dalam memori. Ini hanya kasus normal saat bekerja dengan objek yang bisa berubah dalam python. Ketika Anda bekerja dengan objek yang bisa berubah dalam python Anda harus berhati-hati karena sulit untuk debug. Seperti contoh berikut ini.

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

Niat contoh ini adalah untuk mendapatkan semua id pengguna termasuk id yang diblokir. Itu kami dapatkan dari variabel id tetapi kami juga memperbarui nilai my_users secara tidak sengaja. ketika Anda memperpanjang id dengan blok_id, my_users diperbarui karena id merujuk ke my_users .

Vkreddy Komatireddy
sumber
-1

Menyalin dengan menggunakan for 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
sumber
1
Ini hanya berfungsi untuk kamus sederhana. Mengapa tidak menggunakan deepcopy, yang dibangun secara tegas untuk tujuan ini?
Anthony
Bukan cara terbaik. Respons yang baik di bawah.
David Beauchemin
-6

Anda dapat menggunakan secara langsung:

dict2 = eval(repr(dict1))

di mana objek dict2 adalah salinan independen dict1, sehingga Anda dapat memodifikasi dict2 tanpa mempengaruhi dict1.

Ini berfungsi untuk semua jenis objek.

Viiik
sumber
4
Jawaban ini salah, dan jangan digunakan. Kelas yang ditentukan pengguna, misalnya, mungkin tidak memiliki yang tepat __repr__untuk direkonstruksi dengan eval, juga tidak mungkin kelas objek berada dalam ruang lingkup saat ini untuk dipanggil. Bahkan tetap dengan tipe built-in, ini akan gagal jika objek yang sama disimpan di bawah beberapa tombol, karena dict2kemudian akan memiliki dua objek terpisah. Kamus referensial mandiri, yang dict1berisi kamus itu sendiri, akan berisi kamus tersebut Ellipsis. Akan lebih baik menggunakandict1.copy()
Keju Eldritch
Objek (atau "nilai") tidak diharapkan selalu memiliki representasi yang setia oleh string karakter, tidak dengan cara yang biasa dibaca manusia dalam hal apa pun.
Alexey