Saya memiliki dua kamus Python, dan saya ingin menulis satu ekspresi yang mengembalikan dua kamus ini, digabung. The update()
Metode akan menjadi apa yang saya butuhkan, jika kembali hasilnya bukan memodifikasi kamus di tempat.
>>> x = {'a': 1, 'b': 2}
>>> y = {'b': 10, 'c': 11}
>>> z = x.update(y)
>>> print(z)
None
>>> x
{'a': 1, 'b': 10, 'c': 11}
Bagaimana saya bisa mendapatkan kamus gabungan terakhir z
, bukan x
?
(Supaya lebih jelas, penanganan konflik yang terakhir menang dict.update()
adalah apa yang saya cari juga.)
python
dictionary
merge
Carl Meyer
sumber
sumber
z = x | y
Jawaban:
Untuk kamus
x
dany
,z
jadilah kamus yang dangkal digabung dengan nilaiy
menggantikannyax
.Dalam Python 3.5 atau lebih tinggi:
Dalam Python 2, (atau 3,4 atau lebih rendah) tulis fungsi:
dan sekarang:
Dalam Python 3.9.0a4 atau lebih tinggi (tanggal rilis akhir kira-kira Oktober 2020): PEP-584 , dibahas di sini , diimplementasikan untuk lebih menyederhanakan ini:
Penjelasan
Katakanlah Anda memiliki dua dicts dan Anda ingin menggabungkannya menjadi dict baru tanpa mengubah dicts asli:
Hasil yang diinginkan adalah untuk mendapatkan kamus baru (
z
) dengan nilai-nilai digabungkan, dan nilai-nilai dict kedua menimpa mereka dari yang pertama.Sintaks baru untuk ini, diusulkan dalam PEP 448 dan tersedia pada Python 3.5 , adalah
Dan itu memang satu ekspresi.
Perhatikan bahwa kita juga dapat bergabung dengan notasi literal:
dan sekarang:
Sekarang ditampilkan sebagaimana diimplementasikan dalam jadwal rilis untuk 3,5, PEP 478 , dan sekarang telah membuat jalannya ke Apa yang Baru dalam dokumen Python 3.5 .
Namun, karena banyak organisasi masih menggunakan Python 2, Anda mungkin ingin melakukan ini dengan cara yang kompatibel. Cara klasik Pythonic, tersedia dalam Python 2 dan Python 3.0-3.4, adalah melakukan ini sebagai proses dua langkah:
Dalam kedua pendekatan,
y
akan menjadi yang kedua dan nilainya akan menggantikanx
nilai-nilai, dengan demikian'b'
akan menunjuk3
pada hasil akhir kami.Belum menggunakan Python 3.5, tetapi ingin satu ekspresi
Jika Anda belum menggunakan Python 3.5, atau perlu menulis kode yang kompatibel dengan backward, dan Anda ingin ini dalam satu ekspresi , yang paling performan ketika pendekatan yang benar adalah memasukkannya ke dalam fungsi:
dan kemudian Anda memiliki satu ekspresi:
Anda juga dapat membuat fungsi untuk menggabungkan jumlah dicts yang tidak ditentukan, dari nol ke jumlah yang sangat besar:
Fungsi ini akan berfungsi dalam Python 2 dan 3 untuk semua dicts. mis. dikte yang diberikan
a
kepadag
:dan pasangan nilai kunci
g
akan diutamakan daripada dictsa
untukf
, dan sebagainya.Kritik atas Jawaban Lain
Jangan gunakan apa yang Anda lihat di jawaban yang sebelumnya diterima:
Dalam Python 2, Anda membuat dua daftar dalam memori untuk setiap dict, membuat daftar ketiga di memori dengan panjang yang sama dengan panjang dari dua yang pertama disatukan, dan kemudian membuang ketiga daftar untuk membuat dict. Dalam Python 3, ini akan gagal karena Anda menambahkan dua
dict_items
objek bersamaan, bukan dua daftar -dan Anda harus membuatnya secara eksplisit sebagai daftar, misalnya
z = dict(list(x.items()) + list(y.items()))
. Ini adalah pemborosan sumber daya dan daya komputasi.Demikian pula, mengambil penyatuan
items()
dalam Python 3 (viewitems()
dalam Python 2.7) juga akan gagal ketika nilai-nilai adalah objek yang tidak dapat hancur (seperti daftar, misalnya). Bahkan jika nilai-nilai Anda dapat di hashable, karena set secara semantik tidak tertata, perilaku tidak terdefinisi sehubungan dengan diutamakan. Jadi jangan lakukan ini:Contoh ini menunjukkan apa yang terjadi ketika nilai tidak dapat dihancurkan:
Berikut adalah contoh di mana y harus didahulukan, tetapi nilai dari x dipertahankan karena urutan set arbitrer:
Retasan lain yang tidak boleh Anda gunakan:
Ini menggunakan
dict
konstruktor, dan sangat cepat dan efisien memori (bahkan sedikit lebih dari proses dua langkah kami), tetapi kecuali Anda tahu persis apa yang terjadi di sini (yaitu, dikt kedua dilewatkan sebagai argumen kata kunci ke dikt tersebut constructor), sulit dibaca, ini bukan penggunaan yang dimaksudkan, jadi bukan Pythonic.Berikut adalah contoh penggunaan yang diperbaiki di Django .
Diktik dimaksudkan untuk mengambil kunci hashable (mis. Frozenset atau tuple), tetapi metode ini gagal dalam Python 3 ketika kunci bukan string.
Dari milis , Guido van Rossum, pencipta bahasa, menulis:
dan
Ini adalah pemahaman saya (serta pemahaman pencipta bahasa ) bahwa penggunaan yang dimaksudkan
dict(**y)
adalah untuk membuat dicts untuk tujuan keterbacaan, misalnya:dari pada
Menanggapi komentar
Sekali lagi, ini tidak berfungsi selama 3 ketika kunci non-string. Kontrak panggilan implisit adalah bahwa namespaces mengambil dicts biasa, sementara pengguna hanya harus melewati argumen kata kunci yang bersifat string. Semua callable lainnya memberlakukannya.
dict
mematahkan konsistensi ini dalam Python 2:Ketidakkonsistenan ini buruk mengingat implementasi lain dari Python (Pypy, Jython, IronPython). Jadi itu diperbaiki di Python 3, karena penggunaan ini bisa menjadi perubahan yang melanggar.
Saya serahkan kepada Anda bahwa adalah ketidakmampuan berbahaya untuk sengaja menulis kode yang hanya berfungsi dalam satu versi bahasa atau yang hanya berfungsi dengan batasan arbitrer tertentu.
Lebih banyak komentar:
Tanggapan saya:
merge_two_dicts(x, y)
sebenarnya tampak jauh lebih jelas bagi saya, jika kita benar-benar khawatir tentang keterbacaan. Dan itu tidak kompatibel maju, karena Python 2 semakin usang.Iya. Saya harus merujuk Anda kembali ke pertanyaan, yang meminta gabungan dua kamus yang dangkal , dengan nilai pertama ditimpa oleh yang kedua - dalam satu ekspresi.
Dengan asumsi dua kamus kamus, orang mungkin secara rekursif menggabungkannya dalam satu fungsi, tetapi Anda harus berhati-hati untuk tidak mengubah dikte dari sumber mana pun, dan cara paling pasti untuk menghindari itu adalah dengan membuat salinan ketika menetapkan nilai. Karena kunci harus hashable dan biasanya tidak dapat diubah, tidak ada gunanya menyalinnya:
Pemakaian:
Menghasilkan kontinjensi untuk tipe nilai lain jauh di luar cakupan pertanyaan ini, jadi saya akan mengarahkan Anda pada jawaban saya untuk pertanyaan kanonik pada "Kamus kamus digabung" .
Kurang Berkinerja Tapi Ad-hocs Benar
Pendekatan-pendekatan ini kurang berkinerja, tetapi mereka akan memberikan perilaku yang benar. Mereka akan jauh lebih performant dari
copy
danupdate
atau membongkar baru karena mereka iterate melalui setiap pasangan kunci-nilai pada tingkat yang lebih tinggi dari abstraksi, tetapi mereka melakukan menghormati urutan prioritas (dicts terakhir memiliki diutamakan)Anda juga dapat rantai dicts secara manual di dalam pemahaman dict:
atau dalam python 2.6 (dan mungkin sedini 2.4 ketika ekspresi generator diperkenalkan):
itertools.chain
akan rantai iterator di atas pasangan nilai kunci dalam urutan yang benar:Analisis Kinerja
Saya hanya akan melakukan analisis kinerja penggunaan yang diketahui berperilaku benar.
Berikut ini dilakukan pada Ubuntu 14.04
Dalam Python 2.7 (sistem Python):
Dalam Python 3.5 (deadsnakes PPA):
Sumber pada Kamus
sumber
{**{(0, 1):2}}
->{(0, 1): 2}
z = {**x, **y}
benar - benar merangsang sayax | y
Dalam kasus Anda, yang dapat Anda lakukan adalah:
Ini akan, seperti yang Anda inginkan, masukkan dict terakhir
z
, dan membuat nilai untuk kuncib
ditimpa dengan benar oleh nilaiy
dict kedua ( ):Jika Anda menggunakan Python 3, itu hanya sedikit lebih rumit. Untuk membuat
z
:Jika Anda menggunakan Python versi 3.9.0a4 atau lebih tinggi, maka Anda dapat langsung menggunakan:
sumber
Sebuah alternatif:
sumber
Update
bukan salah satu fungsi "inti" yang cenderung banyak digunakan orang.(lambda z: z.update(y) or z)(x.copy())
: POpsi lain yang lebih ringkas:
Catatan : ini telah menjadi jawaban yang populer, tetapi penting untuk menunjukkan bahwa jika
y
memiliki kunci non-string, fakta bahwa ini berfungsi sama sekali adalah penyalahgunaan detail implementasi CPython, dan itu tidak berfungsi dalam Python 3, atau dalam PyPy, IronPython, atau Jython. Juga, Guido bukan penggemar . Jadi saya tidak bisa merekomendasikan teknik ini untuk kode portabel maju-kompatibel atau lintas-implementasi, yang benar-benar berarti harus dihindari sepenuhnya.sumber
Ini mungkin bukan jawaban yang populer, tetapi Anda hampir pasti tidak ingin melakukan ini. Jika Anda ingin salinan yang merupakan gabungan, gunakan salinan (atau deepcopy , tergantung pada apa yang Anda inginkan) dan kemudian perbarui. Dua baris kode lebih mudah dibaca - lebih Pythonic - daripada pembuatan baris tunggal dengan .items () + .items (). Eksplisit lebih baik daripada implisit.
Selain itu, saat Anda menggunakan .items () (pre Python 3.0), Anda membuat daftar baru yang berisi item dari dikt. Jika kamus Anda besar, maka itu cukup banyak overhead (dua daftar besar yang akan dibuang segera setelah diktat gabungan dibuat). pembaruan () dapat bekerja lebih efisien, karena dapat dijalankan melalui item-demi-item kedua
Dalam hal waktu :
IMO perlambatan kecil antara dua yang pertama adalah layak untuk dibaca. Selain itu, argumen kata kunci untuk pembuatan kamus hanya ditambahkan dalam Python 2.3, sedangkan salin () dan pembaruan () akan berfungsi di versi yang lebih lama.
sumber
Dalam jawaban tindak lanjut, Anda bertanya tentang kinerja relatif dari dua alternatif ini:
Di komputer saya, setidaknya (x86_64 yang cukup biasa menjalankan Python 2.5.2), alternatif
z2
tidak hanya lebih pendek dan lebih sederhana tetapi juga secara signifikan lebih cepat. Anda dapat memverifikasi ini sendiri menggunakantimeit
modul yang disertakan dengan Python.Contoh 1: kamus identik memetakan 20 bilangan bulat berturut-turut untuk diri mereka sendiri:
z2
menang dengan faktor 3,5 atau lebih. Kamus-kamus yang berbeda nampaknya menghasilkan hasil yang sangat berbeda, tetapiz2
sepertinya selalu keluar kedepan. (Jika Anda mendapatkan hasil yang tidak konsisten untuk pengujian yang sama , coba lewati-r
dengan angka yang lebih besar dari standar 3.)Contoh 2: kamus non-tumpang tindih memetakan 252 string pendek ke integer dan sebaliknya:
z2
menang sekitar 10 faktor. Itu kemenangan yang cukup besar dalam buku saya!Setelah membandingkan kedua, saya bertanya-tanya apakah
z1
kinerja yang buruk dapat dikaitkan dengan overhead membangun dua daftar item, yang pada gilirannya membuat saya bertanya-tanya apakah variasi ini mungkin bekerja lebih baik:Beberapa tes cepat, mis
arahkan saya untuk menyimpulkan bahwa
z3
ini agak lebih cepat daripadaz1
, tetapi tidak secepat secepatz2
. Jelas tidak sepadan dengan semua pengetikan ekstra.Diskusi ini masih kehilangan sesuatu yang penting, yang merupakan perbandingan kinerja dari alternatif ini dengan cara "jelas" menggabungkan dua daftar: menggunakan
update
metode ini. Untuk mencoba menjaga semuanya tetap sejajar dengan ekspresi, tidak ada yang memodifikasi x atau y, saya akan membuat salinan x alih-alih mengubahnya di tempat, sebagai berikut:Hasil khas:
Dengan kata lain,
z0
danz2
tampaknya memiliki kinerja yang pada dasarnya identik. Apakah Anda pikir ini kebetulan? Bukan saya....Bahkan, saya akan mengklaim bahwa tidak mungkin kode Python murni untuk melakukan yang lebih baik dari ini. Dan jika Anda dapat melakukan jauh lebih baik dalam modul ekstensi C, saya membayangkan orang-orang Python mungkin tertarik untuk memasukkan kode Anda (atau variasi pada pendekatan Anda) ke dalam inti Python. Penggunaan Python
dict
di banyak tempat; mengoptimalkan operasinya adalah masalah besar.Anda juga dapat menulis ini sebagai
seperti Tony, tetapi (tidak mengherankan) perbedaan notasi ternyata tidak memiliki efek terukur pada kinerja. Gunakan yang terlihat tepat untuk Anda. Tentu saja, dia benar sekali untuk menunjukkan bahwa versi dua pernyataan itu jauh lebih mudah dipahami.
sumber
items()
tidak bisa dipatenkan, daniteritems
tidak ada.Di Python 3.0 dan yang lebih baru , Anda bisa menggunakan
collections.ChainMap
grup mana yang beberapa dicts atau pemetaan lainnya bersama-sama untuk membuat tampilan tunggal yang dapat diperbarui:Pembaruan untuk Python 3.5 dan yang lebih baru : Anda dapat menggunakan pengemasan dan pembongkaran kamus PEP 448 yang diperluas. Ini cepat dan mudah:
sumber
del
mengatakan ChainMap c akan menghapus pemetaan pertama kunci itu.dict
untuk menghindarinya, yaitu:dict(ChainMap({}, y, x))
Saya menginginkan sesuatu yang serupa, tetapi dengan kemampuan untuk menentukan bagaimana nilai pada kunci duplikat digabungkan, jadi saya meretas ini (tapi tidak banyak mengujinya). Jelas ini bukan ekspresi tunggal, tetapi ini adalah panggilan fungsi tunggal.
sumber
Secara rekursif / mendalam perbarui dikt
Demonstrasi:
Output:
Terima kasih rednaw untuk pengeditan.
sumber
Versi terbaik yang bisa saya pikirkan saat tidak menggunakan salinan adalah:
Ini lebih cepat daripada
dict(x.items() + y.items())
tetapi tidak secepatn = copy(a); n.update(b)
, setidaknya pada CPython. Versi ini juga bekerja di Python 3 jika Anda mengubahiteritems()
keitems()
, yang secara otomatis dilakukan oleh alat 2to3.Secara pribadi saya suka versi ini karena ini menggambarkan cukup baik apa yang saya inginkan dalam sintaks fungsional tunggal. Satu-satunya masalah kecil adalah bahwa tidak sepenuhnya jelas bahwa nilai-nilai dari y lebih diutamakan daripada nilai-nilai dari x, tapi saya tidak percaya sulit untuk mencari tahu itu.
sumber
Python 3.5 (PEP 448) memungkinkan opsi sintaksis yang lebih bagus:
Atau bahkan
Dalam Python 3.9 Anda juga menggunakan | dan | = dengan contoh di bawah ini dari PEP 584
sumber
dict(x, **y)
solusi? Seperti yang Anda (@CarlMeyer) sebutkan dalam catatan jawaban Anda sendiri ( stackoverflow.com/a/39858/2798610 ) Guido menganggap solusi itu ilegal .dict(x, **y)
karena alasan (sangat bagus) yang hanya bergantung paday
memiliki kunci yang merupakan nama argumen kata kunci yang valid (kecuali jika Anda menggunakan CPython 2.7, di mana dict constructor menipu). Keberatan / pembatasan ini tidak berlaku untuk PEP 448, yang menggeneralisasikan**
sintaks pembongkaran ke literct. Jadi solusi ini memiliki resolusi yang sama dengandict(x, **y)
, tanpa kelemahan.Untuk item dengan kunci di kedua kamus ('b'), Anda dapat mengontrol mana yang berakhir di output dengan menempatkan yang terakhir.
sumber
Sementara pertanyaan sudah dijawab beberapa kali, solusi sederhana untuk masalah ini belum terdaftar.
Ini secepat z0 dan z2 jahat yang disebutkan di atas, tetapi mudah dimengerti dan diubah.
sumber
z4 = {}
dan ubah baris berikutnya kez4 = x.copy()
- lebih baik dari kode yang baik tidak melakukan hal-hal yang tidak perlu (yang membuatnya lebih mudah dibaca dan dipelihara).Di antara jawaban yang teduh dan meragukan, contoh cemerlang ini adalah satu-satunya cara yang baik untuk menggabungkan dikte dengan Python, disahkan oleh diktator seumur hidup Guido van Rossum sendiri! Orang lain menyarankan setengah dari ini, tetapi tidak menjalankannya.
memberi:
sumber
Jika Anda berpikir lambda itu jahat maka jangan baca lebih lanjut. Seperti yang diminta, Anda dapat menulis solusi cepat dan efisien memori dengan satu ekspresi:
Seperti yang disarankan di atas, menggunakan dua baris atau menulis fungsi mungkin merupakan cara yang lebih baik.
sumber
Menjadi pythonic. Gunakan pemahaman :
sumber
def dictmerge(*args): return {i:d[i] for d in args for i in d}
z={k: v for d in (x, y) for k, v in d.items()}
Dalam python3,
items
metode ini tidak lagi mengembalikan daftar , melainkan tampilan , yang bertindak seperti set. Dalam hal ini Anda harus mengambil serikat yang ditetapkan karena bergabung dengan+
tidak akan bekerja:Untuk perilaku seperti python3 di versi 2.7,
viewitems
metode ini harus berfungsi sebagai penggantiitems
:Saya lebih suka notasi ini karena tampaknya lebih alami untuk menganggapnya sebagai operasi persatuan daripada gabungan (seperti yang ditunjukkan judulnya).
Edit:
Beberapa poin lagi untuk python 3. Pertama, perhatikan bahwa
dict(x, **y)
trik ini tidak akan bekerja di python 3 kecuali kunci-kunci di dalamy
adalah string.Juga, jawaban Chainmap Raymond Hettinger cukup elegan, karena dapat menggunakan jumlah dicts sebagai arbitrer, tetapi dari dokumen itu sepertinya berurutan melihat daftar semua dicts untuk setiap pencarian:
Ini dapat memperlambat Anda jika Anda memiliki banyak pencarian di aplikasi Anda:
Jadi tentang urutan besarnya lebih lambat untuk pencarian. Saya penggemar Chainmap, tetapi terlihat kurang praktis di mana mungkin ada banyak pencarian.
sumber
Penyalahgunaan mengarah ke solusi satu ekspresi untuk jawaban Matius :
Anda bilang Anda menginginkan satu ekspresi, jadi saya menyalahgunakan
lambda
untuk mengikat nama, dan tuple untuk mengesampingkan batas satu ekspresi lambda. Merasa ngeri.Anda juga bisa melakukan ini tentu saja jika Anda tidak mau menyalinnya:
sumber
Solusi sederhana menggunakan itertools yang menjaga ketertiban (dicts terakhir diutamakan)
Dan penggunaannya:
sumber
Dua kamus
dan kamus
sum
memiliki kinerja yang buruk. Lihat https://mathieularose.com/how-not-to-flatten-a-list-of-lists-in-python/sumber
Meskipun jawabannya baik untuk kamus dangkal ini , tidak ada metode yang didefinisikan di sini yang benar-benar menggabungkan kamus dalam.
Contohnya mengikuti:
Orang akan mengharapkan hasil dari sesuatu seperti ini:
Sebaliknya, kami mendapatkan ini:
Entri 'satu' harus memiliki 'depth_2' dan 'ekstra' sebagai item di dalam kamusnya jika benar-benar merupakan penggabungan.
Menggunakan rantai juga tidak berfungsi:
Hasil dalam:
Penggabungan mendalam yang diberikan rcwesick juga menciptakan hasil yang sama.
Ya, itu akan berhasil untuk menggabungkan kamus sampel, tetapi tidak satupun dari mereka adalah mekanisme umum untuk bergabung. Saya akan memperbarui ini nanti setelah saya menulis metode yang melakukan penggabungan yang benar.
sumber
(Hanya untuk Python2.7 *; ada solusi yang lebih sederhana untuk Python3 *.)
Jika Anda tidak keberatan mengimpor modul perpustakaan standar, Anda dapat melakukannya
(
or a
Bit dalamlambda
diperlukan karenadict.update
selalu mengembalikanNone
kesuksesan.)sumber
Jika Anda tidak keberatan bermutasi
x
,Sederhana, mudah dibaca, pemain. Anda tahu
update()
selalu kembaliNone
, yang merupakan nilai salah. Jadi ungkapan di atas akan selalu dievaluasix
, setelah memperbaruinya.Metode bermutasi di perpustakaan standar (seperti
.update()
) kembaliNone
dengan konvensi, jadi pola ini juga akan bekerja pada mereka. Jika Anda menggunakan metode yang tidak mengikuti konvensi ini, makaor
mungkin tidak berfungsi. Tapi, Anda bisa menggunakan tampilan tuple dan mengindeks untuk membuatnya menjadi ekspresi tunggal. Ini berfungsi terlepas dari apa elemen pertama mengevaluasi.Jika Anda belum memiliki
x
variabel, Anda dapat menggunakanlambda
untuk membuat lokal tanpa menggunakan pernyataan tugas. Jumlah ini menggunakanlambda
sebagai ekspresi let , yang merupakan teknik umum dalam bahasa fungsional, tapi mungkin unpythonic.Meskipun tidak jauh berbeda dengan penggunaan operator walrus baru berikut (hanya Python 3.8+):
Jika Anda menginginkan salinan, gaya PEP 448 paling mudah
{**x, **y}
. Tetapi jika itu tidak tersedia di versi Python (lama) Anda, pola let berfungsi di sini juga.(Itu, tentu saja, setara dengan
(z := x.copy()).update(y) or z
, tetapi jika versi Python Anda cukup baru untuk itu, maka gaya PEP 448 akan tersedia.)sumber
Menggambar pada ide di sini dan di tempat lain saya telah memahami suatu fungsi:
Penggunaan (diuji dengan python 3):
Anda bisa menggunakan lambda sebagai gantinya.
sumber
Masalah yang saya miliki dengan solusi yang terdaftar hingga saat ini adalah bahwa, dalam kamus yang digabungkan, nilai untuk kunci "b" adalah 10 tetapi, menurut cara berpikir saya, itu harus 12. Dalam hal itu, saya menyajikan yang berikut:
Hasil:
sumber
cytoolz.merge_with
( toolz.readthedocs.io/en/latest/… )Sangat konyol sehingga
.update
tidak menghasilkan apa-apa.Saya hanya menggunakan fungsi pembantu sederhana untuk memecahkan masalah:
Contoh:
sumber
Ini harus menyelesaikan masalah Anda.
sumber
Ini dapat dilakukan dengan pemahaman dict tunggal:
Dalam pandangan saya jawaban terbaik untuk bagian 'ekspresi tunggal' karena tidak ada fungsi tambahan yang diperlukan, dan itu pendek.
sumber
Akan ada opsi baru ketika Python 3.8 rilis ( dijadwalkan untuk 20 Oktober 2019) ), terima kasih kepada PEP 572: Ekspresi Penugasan . Operator ekspresi tugas baru
:=
memungkinkan Anda untuk menetapkan hasilcopy
dan masih menggunakannya untuk memanggilupdate
, meninggalkan kode gabungan satu ekspresi, daripada dua pernyataan, mengubah:untuk:
sementara berperilaku identik dalam segala hal. Jika Anda juga harus mengembalikan hasilnya
dict
(Anda meminta ekspresi yang mengembalikandict
; yang di atas membuat dan menetapkannewdict
, tetapi tidak mengembalikannya, jadi Anda tidak bisa menggunakannya untuk meneruskan argumen ke fungsi apa adanya, alamyfunc((newdict := dict1.copy()).update(dict2))
) , lalu tambahkan sajaor newdict
sampai akhir (sejakupdate
returnNone
, yang salah, ia akan mengevaluasi dan kembalinewdict
sebagai hasil dari ekspresi):Peringatan penting: Secara umum, saya akan mengecilkan pendekatan ini demi:
Pendekatan membongkar lebih jelas (bagi siapa pun yang tahu tentang pembongkaran umum di tempat pertama, yang harus Anda lakukan ), tidak memerlukan nama untuk hasilnya sama sekali (jadi jauh lebih ringkas ketika membangun sementara yang segera diteruskan ke sebuah fungsi atau termasuk dalam
list
/tuple
literal atau sejenisnya), dan hampir pasti lebih cepat juga, karena (pada CPython) kira-kira setara dengan:tetapi dilakukan pada lapisan C, menggunakan
dict
API beton , sehingga tidak ada metode dinamis lookup / binding atau overhead panggilan fungsi pengiriman yang terlibat (di mana(newdict := dict1.copy()).update(dict2)
tak terhindarkan identik dengan perilaku dua-liner asli, melakukan pekerjaan dalam langkah-langkah terpisah, dengan pencarian dinamis / mengikat / doa metode.Ini juga lebih dapat diperluas, karena menggabungkan tiga
dict
s sudah jelas:di mana menggunakan ekspresi penugasan tidak akan skala seperti itu; yang terdekat dengan Anda adalah:
atau tanpa
None
t sementara sementara , tetapi dengan pengujian kebenaran dari setiapNone
hasil:salah satu dari yang jelas jauh lebih buruk, dan termasuk inefisiensi lebih lanjut (baik terbuang sementara
tuple
dariNone
s untuk pemisahan koma, atau pengujian truthiness sia-sia setiapupdate
'sNone
imbalanor
pemisahan).Satu-satunya keuntungan nyata untuk pendekatan ekspresi penugasan terjadi jika:
set
s dandict
s (keduanya mendukungcopy
danupdate
, jadi kodenya berfungsi kurang lebih seperti yang Anda harapkan)dict
dirinya sendiri, dan harus menjaga jenis dan semantik sisi kiri (daripada berakhir dengan datarandict
). Meskipunmyspecialdict({**speciala, **specialb})
mungkin bekerja, itu akan melibatkan ekstra temporerdict
, dan jikamyspecialdict
memiliki fitur yangdict
tidak dapat dipertahankan (mis. Regulerdict
sekarang mempertahankan pesanan berdasarkan tampilan pertama kunci, dan nilai berdasarkan tampilan kunci terakhir; Anda mungkin ingin salah satu yang mempertahankan ketertiban berdasarkan yang terakhirpenampilan kunci sehingga memperbarui nilai juga memindahkannya ke akhir), maka semantik akan salah. Karena versi ekspresi penugasan menggunakan metode yang dinamai (yang mungkin kelebihan beban untuk berperilaku sesuai), itu tidak pernah membuatdict
sama sekali (kecualidict1
sudah adict
), melestarikan tipe asli (dan semantik tipe asli), sambil menghindari sementara.sumber
sumber
x
dengan salinannya. Jikax
argumen fungsi ini tidak akan berfungsi (lihat contoh )