Ini bukan pertanyaan tentang sifat mengetik bebek dan lebih banyak tentang tetap pythonic, saya kira.
Pertama-tama - ketika berhadapan dengan dikt, khususnya ketika struktur dikt cukup dapat diprediksi dan kunci yang diberikan biasanya tidak ada tetapi kadang-kadang ada, saya pertama kali memikirkan dua pendekatan:
if myKey in dict:
do_some_work(dict[myKey])
else:
pass
Dan tentu saja Ye Olde pendekatan 'maaf vs izin'.
try:
do_some_work(dict[myKey])
except KeyError:
pass
Sebagai seorang pria pekerja harian Python, saya merasa seperti saya melihat yang terakhir disukai banyak, yang hanya terasa aneh kurasa karena dalam Python docs try/excepts
tampaknya lebih disukai ketika ada kesalahan yang sebenarnya, yang bertentangan dengan, um ... tidak adanya kesuksesan?
Jika dikte sesekali tidak memiliki kunci dalam myDict, dan diketahui bahwa itu tidak akan selalu memiliki kunci itu, apakah percobaan / kecuali secara kontekstual menyesatkan? Ini bukan kesalahan pemrograman, ini hanya fakta dari data - dikt ini hanya tidak memiliki kunci tertentu.
Ini tampaknya sangat penting ketika Anda melihat sintaks coba / kecuali / lain, yang terlihat sangat berguna ketika datang untuk memastikan bahwa mencoba tidak menangkap terlalu banyak kesalahan. Anda dapat melakukan sesuatu seperti:
try:
foo += bar
except TypeError:
pass
else:
return some_more_work(foo)
Bukankah itu akan menyebabkan menelan semua jenis kesalahan aneh yang mungkin merupakan hasil dari beberapa kode buruk? Kode di atas mungkin hanya mencegah Anda melihat bahwa Anda mencoba untuk menambahkan 2 + {}
dan Anda mungkin tidak pernah menyadari bahwa beberapa bagian dari kode Anda telah salah besar. Saya tidak menyarankan bahwa kita harus Memeriksa Semua Jenis, itu sebabnya itu Python dan bukan JavaScript - tapi sekali lagi dengan konteks coba / kecuali, sepertinya itu seharusnya menangkap program melakukan sesuatu yang seharusnya tidak dilakukan, sebagai gantinya memungkinkan untuk melanjutkan.
Saya menyadari contoh di atas adalah sesuatu dari argumen manusia jerami, dan pada kenyataannya sengaja buruk. Tetapi mengingat kredo pythonic better to ask forgiveness than permission
saya tidak bisa membantu tetapi merasa seperti itu menimbulkan pertanyaan di mana garis di pasir sebenarnya adalah antara aplikasi yang benar jika / selain vs coba / kecuali adalah, khususnya ketika Anda tahu apa yang diharapkan dari data yang Anda kerjakan.
Saya bahkan tidak berbicara tentang masalah kecepatan atau praktik terbaik di sini, saya hanya agak diam-diam bingung dengan diagram Venn yang dirasakan tentang kasus-kasus di mana sepertinya itu bisa berjalan baik, tetapi orang-orang keliru dalam upaya mencoba / kecuali karena 'seseorang di suatu tempat mengatakan itu Pythonic'. Sudahkah saya menarik kesimpulan yang salah tentang penerapan sintaks ini?
Jawaban:
Gunakan metode get saja:
... di mana
default_value
nilai dikembalikan jikathe_key
tidak dalamsome_dict
. Jika Anda menghilangkandefault_value
,None
dikembalikan jika kunci tidak ada.Secara umum, dalam Python, orang cenderung lebih suka mencoba / kecuali daripada memeriksa sesuatu terlebih dahulu - lihat entri EAFP di glosarium . Perhatikan bahwa banyak fungsi "tes untuk keanggotaan" menggunakan pengecualian di belakang layar.
sumber
dict
dan melakukan pekerjaan berdasarkan apa yang ditemukan, rasanya sepertiif myDict.get(a_key) is not None: do_work(myDict[a_key])
lebih Wordier dan contoh lain dari tampilan implisit sebelum melompat - ditambah IMHO sedikit lebih mudah dibaca. Mungkin saya tidak mengertidict.get(a_key, a_default)
dalam konteks yang benar, tetapi sepertinya ini adalah awal dari penulisan 'not-a-switch-statement if / elses' atau nilai magis. Saya suka apa yang dilakukan metode ini, saya akan memeriksanya lebih dalam.data = myDict.get(a_key, default)
dando_work
akan melakukan hal yang benar ketika diberikandefault
(mis.None
) Atau Anda lakukanif data: do_work(data)
. Hanya satu pencarian diperlukan dalam kedua kasus. (Mungkinif data is not None: ...
, dalam kedua kasus itu, masih hanya satu pencarian dan kemudian logika Anda sendiri dapat mengambil alih.)try/except/else
sampah yang tampak mengerikan dan secara keseluruhan meningkatkan IMHO keterbacaan kode saya. Saya telah belajar pelajaran berharga yang pernah saya dengar sebelumnya tetapi gagal untuk mengingat: "Jika Anda merasa terlalu banyak menulis kode, berhentilah dan lihat fitur-fitur bahasa." Terima kasih!!Apakah kunci yang hilang merupakan aturan atau pengecualian ?
Dari sudut pandang pragmatis, melempar / menangkap jauh lebih lambat daripada memeriksa apakah kuncinya ada dalam tabel. Jika kunci yang hilang adalah kejadian umum - Anda harus menggunakan kondisi.
Hal lain yang mendukung kondisi adalah klausa lain - jauh lebih mudah untuk memahami ketika salah satu blok jika dijalankan, pertimbangkan bahwa bahkan kelas pengecualian yang sama dapat dilemparkan dari beberapa pernyataan di blok coba.
Kode dalam kecuali klausa tidak boleh menjadi bagian dari cacat normal (mis. Jika kunci tidak ada, tambahkan) - itu harus menangani kesalahan.
sumber
try
/catch
versi lebih cepat.Dalam semangat menjadi "pythonic" dan, khususnya, mengetik bebek - coba / kecuali terlihat hampir rapuh bagi saya.
Yang Anda inginkan hanyalah sesuatu dengan akses seperti dict, tetapi
__getitem__
dapat diganti untuk melakukan sesuatu yang tidak sesuai harapan Anda. Misalnya, menggunakandefaultdict
dari perpustakaan standar:Karena nilai pengembalian defaultnya adalah Falsy, pengecekan akses seperti itu akan berfungsi sebagian besar waktu dengan baik .. Tampaknya juga menjaga kode tetap sederhana, itulah sebabnya rekan kerja saya dan saya telah melakukannya selama berbulan-bulan.
Sayangnya, beberapa bulan kemudian, kunci tambahan ini benar-benar berakhir menyebabkan masalah dan bug yang sulit dilacak, karena
0
menjadi nilai yang valid. Dan kadang-kadang kita akan menggunakanin
untuk memeriksa apakah kunci ada, membuat kode melakukan hal-hal yang berbeda padahal seharusnya identik.Alasan saya menyarankan itu terlihat rusak adalah karena dalam semangat pengetikan bebek Python, semua yang Anda inginkan adalah sesuatu seperti dict, dan
defaultdict
cocok dengan persyaratan itu, seperti halnya benda apa pun yang mungkin Anda buat yang mewarisinyadict
. Anda tidak dapat menjamin penelepon tidak akan mengubah implementasinya nanti, jadi Anda harus melakukan hal dengan efek samping paling sedikit.Gunakan versi pertama
if myKey in mydict
,.Juga, perhatikan bahwa ini secara khusus tentang contoh dalam pertanyaan. Pengakuan python "Lebih baik untuk meminta maaf daripada izin" sebagian besar dimaksudkan untuk memastikan Anda benar-benar bertindak dengan benar ketika Anda tidak mendapatkan apa yang Anda inginkan. Misalnya, memeriksa apakah ada file dan kemudian mencoba membacanya - setidaknya 3 hal yang dapat saya pikirkan di atas kepala saya bisa salah:
Yang pertama Anda dapat mencoba untuk "meminta izin", tetapi pada dasarnya kondisi ras itu tidak selalu berhasil; yang kedua terlalu mudah untuk dilupakan; dan yang ketiga tidak dapat diperiksa tanpa mencoba membaca file. Dalam hal apapun, apa yang Anda lakukan setelah gagal hampir pasti akan sama, sehingga dalam hal ini contoh, adalah lebih baik untuk "meminta maaf" dengan menggunakan mencoba / kecuali.
sumber