Saya memiliki kamus bersarang. Apakah hanya ada satu cara untuk mendapatkan nilai dengan aman?
try:
example_dict['key1']['key2']
except KeyError:
pass
Atau mungkin python memiliki metode seperti get()
untuk kamus bersarang?
python
dictionary
methods
except
Arti
sumber
sumber
except keyerror:
klausa.Jawaban:
Anda bisa menggunakan
get
dua kali:Ini akan kembali
None
jika salah satukey1
ataukey2
tidak ada.Perhatikan bahwa ini masih bisa menaikkan
AttributeError
jikaexample_dict['key1']
ada tetapi bukan dict (atau objek seperti dict denganget
metode). Thetry..except
kode yang diposting akan menaikkanTypeError
bukan jikaexample_dict['key1']
adalah unsubscriptable.Perbedaan lainnya adalah bahwa
try...except
hubungan arus pendek segera setelah kunci pertama hilang. Rantaiget
panggilan tidak.Jika Anda ingin mempertahankan sintaks,
example_dict['key1']['key2']
tetapi tidak ingin itu meningkatkan KeyErrors, maka Anda bisa menggunakan resep Hasher :Perhatikan bahwa ini mengembalikan Hasher kosong ketika kunci hilang.
Karena
Hasher
merupakan subkelas daridict
Anda dapat menggunakan Hasher dengan cara yang sama seperti Anda dapat menggunakan adict
. Semua metode dan sintaksis yang sama tersedia, Hashers hanya memperlakukan kunci yang hilang secara berbeda.Anda dapat mengubah biasa
dict
menjadiHasher
seperti ini:dan mengonversi a
Hasher
menjadi regulerdict
dengan mudah:Alternatif lain adalah menyembunyikan keburukan dalam fungsi pembantu:
Sehingga sisa kode Anda dapat tetap terbaca:
sumber
safeget
metode adalah dalam banyak cara tidak sangat aman karena menimpa kamus asli, yang berarti Anda tidak dapat dengan aman melakukan hal-hal sepertisafeget(dct, 'a', 'b') or safeget(dct, 'a')
.safeget
jangan pernah menimpa kamus asli. Ini akan mengembalikan kamus asli, nilai dari kamus asli, atauNone
.dct = dct[key]
menugaskan kembali nilai baru ke variabel lokaldct
. Ini tidak mengubah mutasi asli (jadi dict asli tidak terpengaruh olehsafeget
.) Jika, di sisi lain,dct[key] = ...
telah digunakan, maka dict asli akan diubah. Dengan kata lain, dalam nama Python terikat dengan nilai . Penugasan nilai baru ke nama tidak memengaruhi nilai lama (kecuali jika tidak ada lagi referensi ke nilai lama, dalam hal ini (dalam CPython) akan dikumpulkan sampah.)Anda juga bisa menggunakan pengurangan python :
sumber
Dengan menggabungkan semua jawaban ini di sini dan perubahan kecil yang saya buat, saya pikir fungsi ini akan berguna. ini aman, cepat, mudah dirawat.
Contoh:
sumber
deep_get({'a': 1}, "a.b")
memberiNone
tetapi saya akan mengharapkan pengecualian sepertiKeyError
atau sesuatu yang lain.None
keRaise KeyError
Membangun jawaban Yoav, pendekatan yang bahkan lebih aman:
sumber
Solusi rekursif. Ini bukan yang paling efisien tetapi saya merasa sedikit lebih mudah dibaca daripada contoh lain dan tidak bergantung pada functools.
Contoh
Versi yang lebih halus
sumber
Sementara pendekatan pengurangan rapi dan pendek, saya pikir loop sederhana lebih mudah untuk grok. Saya juga menyertakan parameter default.
Sebagai latihan untuk memahami bagaimana mengurangi satu-liner bekerja, saya melakukan hal berikut. Tetapi pada akhirnya pendekatan loop tampaknya lebih intuitif bagi saya.
Pemakaian
sumber
Saya sarankan Anda untuk mencoba
python-benedict
.Ini adalah
dict
subclass yang menyediakan dukungan keypath dan banyak lagi.Instalasi:
pip install python-benedict
sekarang Anda dapat mengakses nilai bersarang menggunakan keypath :
atau akses nilai bersarang menggunakan daftar kunci :
Ini diuji dengan baik dan open-source di GitHub :
https://github.com/fabiocaccamo/python-benedict
sumber
d.get('a.b[0].c[-1]')
Kelas sederhana yang dapat membungkus dict, dan mengambil berdasarkan kunci:
Sebagai contoh:
Jika kunci tidak ada, itu kembali
None
secara default. Anda dapat mengesampingkannya menggunakandefault=
kunci dalamFindDict
pembungkus - misalnya`:sumber
untuk pengambilan kunci tingkat kedua, Anda dapat melakukan ini:
sumber
Setelah melihat ini untuk mendapatkan atribut mendalam, saya membuat yang berikut untuk mendapatkan
dict
nilai tersarang dengan aman menggunakan notasi titik. Ini berfungsi untuk saya karenadicts
objek MongoDB saya deserialisasi, jadi saya tahu nama kunci tidak mengandung.
s. Juga, dalam konteks saya, saya bisa menentukan nilai fallback palsu (None
) yang tidak saya miliki di data saya, jadi saya bisa menghindari pola coba / kecuali saat memanggil fungsi.sumber
fallback
sebenarnya tidak digunakan dalam fungsi..
sep=','
argumen kata kunci untuk menggeneralisasi untuk kondisi tertentu (sep, mundur). Dan @denvar, jikaobj
mengatakan tipeint
setelah urutan pengurangan, maka obj [nama] memunculkan TypeError, yang saya tangkap. Jika saya menggunakan obj.get (nama) atau obj.get (nama, fallback) sebagai gantinya, itu akan meningkatkan AttributeError, jadi saya harus menangkapnya.Namun fungsi lain untuk hal yang sama, juga mengembalikan boolean untuk mewakili apakah kunci itu ditemukan atau tidak dan menangani beberapa kesalahan yang tidak terduga.
contoh penggunaan:
sumber
Anda dapat menggunakan pydash:
https://pydash.readthedocs.io/en/latest/api.html
sumber
Adaptasi jawaban unutbu yang menurut saya berguna dalam kode saya sendiri:
Ini menghasilkan entri kamus untuk key1 jika belum memiliki kunci itu sehingga Anda menghindari KeyError. Jika Anda ingin membuat kamus bersarang yang menyertakan pasangan kunci itu seperti yang saya lakukan, ini sepertinya solusi termudah.
sumber
Karena meningkatkan kesalahan kunci jika salah satu kunci tidak ada adalah hal yang wajar untuk dilakukan, kita bahkan tidak dapat memeriksanya dan membuatnya tunggal seperti itu:
sumber
Sedikit perbaikan pada
reduce
pendekatan untuk membuatnya bekerja dengan daftar. Juga menggunakan jalur data sebagai string yang dibagi dengan titik, bukan array.sumber
Sebuah solusi yang saya gunakan yang mirip dengan get ganda tetapi dengan kemampuan tambahan untuk menghindari TypeError menggunakan logika if else:
Namun, semakin bersarang kamus semakin rumit ini menjadi.
sumber
Untuk pencarian kamus / pencarian JSON, Anda dapat menggunakan diktor
pip instal dictor
objek dikt
untuk mendapatkan item Lonestar, cukup sediakan jalur terpisah-titik, yaitu
Anda dapat memberikan nilai cadangan jika kuncinya tidak ada di jalur
ada banyak opsi yang dapat Anda lakukan, seperti abaikan casing huruf dan menggunakan karakter lain selain '.' sebagai pemisah jalur,
https://github.com/perfecto25/dictor
sumber
Saya sedikit mengubah jawaban ini . Saya menambahkan memeriksa apakah kita menggunakan daftar dengan angka. Jadi sekarang kita bisa menggunakannya dengan cara apa pun.
deep_get(allTemp, [0], {})
ataudeep_get(getMinimalTemp, [0, minimalTemperatureKey], 26)
lainnyasumber
Sudah ada banyak jawaban bagus tapi saya telah datang dengan fungsi yang disebut get mirip dengan lodash dapatkan di JavaScript yang juga mendukung mencapai ke daftar dengan indeks:
sumber