Bagaimana Anda memeriksa apakah variabel adalah kamus dengan python?
Sebagai contoh, saya ingin untuk mengulang nilai-nilai dalam kamus sampai menemukan kamus. Kemudian, lewati yang ditemukannya:
dict = {'abc': 'abc', 'def': {'ghi': 'ghi', 'jkl': 'jkl'}}
for k, v in dict.iteritems():
if ###check if v is a dictionary:
for k, v in v.iteritems():
print(k, ' ', v)
else:
print(k, ' ', v)
python
dictionary
Riley
sumber
sumber
isinstance(v, collections.abc.Mapping)
. Dengan kata lain, ini bukan duplikat tepat dari "Perbedaan antara isinstance () dan type ()."Jawaban:
Anda dapat menggunakan
if type(ele) is dict
atau menggunakanisinstance(ele, dict)
yang akan berfungsi jika Anda telah mensubklasifikasikandict
:sumber
isinstance(ele, collections.Mapping)
. Ia bekerja untukdict()
,collections.OrderedDict()
, dancollections.UserDict()
. Contoh dalam pertanyaan ini cukup spesifik untuk jawaban Padriac untuk bekerja, tetapi itu tidak cukup baik untuk kasus umum.ele.items()
mengapa Anda memeriksa tipe? EAFP / bebek-mengetik bekerja di sini, hanya membungkusfor k,v in ele.items()
ditry...except (AttributeError, TypeError)
. Jika pengecualian dinaikkan, Anda tahuele
tidak adaitems
yang menghasilkan iterable ...items()
metode 2. yang kebetulan menghasilkan iterable dan 3. di mana setiap elemen iterable dapat direpresentasikan sebagai 2 -Tuple. Pada titik ini objek kustom Anda sudah menerapkan setengah dari dikt. Untuk keperluan kode yang tercantum, kami hanya peduli tentang perluasan bersyarat elemen bersarang, dan objek kustom Anda sudah mengimplementasikannya. (Agak ironis bahwa Anda mengkritik komentar @Alexander Ryzhov karena terlalu umum tetapi sekarang mengajukan kasus umum)items()
yang menghasilkan iterable bersarang).collections.abc.Mapping
, catatan mungkin sesuai bahwa mereka sama, tetapicollections.abc
tidak tersedia sebelum Python 3.3.collections.Mapping
alias masih tersedia di Python 3.6, tetapi tidak didokumentasikan, jadi mungkin orang harus memilihcollections.abc.Maping
.Ini adalah pertanyaan yang sangat bagus, tetapi sangat disayangkan bahwa jawaban yang paling dipilih mengarah dengan rekomendasi yang buruk
type(obj) is dict
,.(Perhatikan bahwa Anda juga tidak boleh menggunakan
dict
sebagai nama variabel - itu adalah nama objek bawaan.)Jika Anda menulis kode yang akan diimpor dan digunakan oleh orang lain, jangan menganggap bahwa mereka akan menggunakan dict builtin secara langsung - membuat anggapan itu membuat kode Anda lebih tidak fleksibel dan dalam hal ini, buat bug yang mudah disembunyikan yang tidak akan membuat kesalahan program. .
Saya sangat menyarankan, untuk keperluan koreksi, pemeliharaan, dan fleksibilitas untuk pengguna di masa depan, jangan pernah memiliki ekspresi yang kurang fleksibel dan tidak otomatis dalam kode Anda ketika ada lebih banyak, ekspresi idiomatik yang lebih fleksibel.
is
adalah tes untuk identitas objek . Itu tidak mendukung warisan, tidak mendukung abstraksi apa pun, dan tidak mendukung antarmuka.Jadi saya akan memberikan beberapa opsi yang bisa dilakukan.
Mendukung warisan:
Ini adalah rekomendasi pertama saya akan membuat, karena memungkinkan pengguna untuk memasok subclass mereka sendiri dict, atau
OrderedDict
,defaultdict
atauCounter
dari koleksi modul:if isinstance(any_object, dict):
Tetapi ada opsi yang bahkan lebih fleksibel.
Abstraksi pendukung:
Ini memungkinkan pengguna kode Anda untuk menggunakan implementasi kustom mereka sendiri dari Pemetaan abstrak, yang juga mencakup subkelas dari
dict
, dan masih mendapatkan perilaku yang benar.Gunakan antarmuka
Anda biasanya mendengar saran OOP, "program ke antarmuka".
Strategi ini mengambil keuntungan dari polimorfisme Python atau mengetik bebek.
Jadi coba saja untuk mengakses antarmuka, menangkap kesalahan yang diharapkan spesifik (
AttributeError
jika tidak ada.items
danTypeError
dalam kasusitems
tidak dapat dipanggil) dengan mundur yang masuk akal - dan sekarang setiap kelas yang mengimplementasikan antarmuka itu akan memberi Anda barang-barangnya (catatan.iteritems()
hilang dengan Python 3):Mungkin Anda mungkin berpikir menggunakan itik mengetik seperti ini terlalu jauh memungkinkan terlalu banyak kesalahan positif, dan mungkin saja, tergantung pada tujuan Anda untuk kode ini.
Kesimpulan
Jangan gunakan
is
untuk memeriksa jenis untuk aliran kontrol standar. Gunakanisinstance
, pertimbangkan abstraksi sepertiMapping
atauMutableMapping
, dan pertimbangkan untuk menghindari pengecekan tipe, menggunakan antarmuka secara langsung.sumber
OP tidak mengecualikan variabel awal, jadi untuk kelengkapan di sini adalah bagaimana menangani kasus umum pemrosesan kamus yang mungkin menyertakan item sebagai kamus.
Juga mengikuti cara Python murni (3.8) yang direkomendasikan untuk menguji kamus dalam komentar di atas.
sumber
dict.iteritems()
tidak ada di Python 3, Anda harus menggunakannyadict.items()
.