Apakah ada alasan untuk memutuskan mana try
atau if
membangun yang akan digunakan, ketika menguji variabel untuk memiliki nilai?
Misalnya, ada fungsi yang mengembalikan daftar atau tidak mengembalikan nilai. Saya ingin memeriksa hasilnya sebelum memprosesnya. Manakah dari berikut ini yang lebih disukai dan mengapa?
result = function();
if (result):
for r in result:
#process items
atau
result = function();
try:
for r in result:
#process items
except TypeError:
pass;
Jawaban:
Anda sering mendengar bahwa Python mendorong gaya EAFP ("lebih mudah untuk meminta maaf daripada izin") daripada gaya LBYL ("lihat sebelum Anda melompat"). Bagi saya, ini masalah efisiensi dan keterbacaan.
Dalam contoh Anda (katakan bahwa alih-alih mengembalikan daftar atau string kosong, fungsinya adalah mengembalikan daftar atau
None
), jika Anda berharap 99% dari wakturesult
itu benar-benar akan mengandung sesuatu yang dapat diubah, saya akan menggunakantry/except
pendekatan. Akan lebih cepat jika pengecualian benar-benar luar biasa. Jikaresult
iniNone
lebih dari 50% dari waktu, kemudian menggunakanif
mungkin lebih baik.Untuk mendukung ini dengan beberapa pengukuran:
Jadi, sementara sebuah
if
pernyataan selalu membebani Anda, hampir bebas untuk membuattry/except
blok. Tetapi ketikaException
benar - benar terjadi, biayanya jauh lebih tinggi.Moral:
try/except
untuk kontrol aliran,Exception
s sebenarnya luar biasa.Dari dokumen Python:
sumber
try/except
adalah 25% lebih cepat daripadaif key in d:
untuk kasus-kasus di mana kuncinya ada di kamus. Itu jauh lebih lambat ketika kunci tidak ada dalam kamus, seperti yang diharapkan, dan konsisten dengan jawaban ini.1/1
dengan timeit bukanlah pilihan yang bagus, karena mereka akan dioptimalkan (lihatdis.dis('1/1')
dan perhatikan bahwa tidak ada pembagian yang terjadi).Fungsi Anda seharusnya tidak mengembalikan tipe campuran (yaitu daftar atau string kosong). Seharusnya mengembalikan daftar nilai atau hanya daftar kosong. Maka Anda tidak perlu menguji apa pun, yaitu kode Anda runtuh menjadi:
sumber
Harap abaikan solusi saya jika kode yang saya berikan tidak jelas pada pandangan pertama dan Anda harus membaca penjelasan setelah sampel kode.
Dapatkah saya berasumsi bahwa "tidak ada nilai yang dikembalikan" berarti nilai kembali adalah Tidak ada? Jika ya, atau jika "tidak ada nilai" adalah Boolean-bijaksana Salah, Anda dapat melakukan hal berikut, karena kode Anda pada dasarnya memperlakukan "tidak ada nilai" sebagai "jangan diulang":
Jika
function()
mengembalikan sesuatu yang tidak Benar, Anda beralih di atas tuple kosong, yaitu Anda tidak menjalankan iterasi apa pun. Ini pada dasarnya adalah LBYL.sumber
Contoh kedua Anda rusak - kode tidak akan pernah membuang pengecualian TypeError karena Anda dapat beralih melalui string dan daftar. Iterasi melalui string atau daftar kosong juga valid - itu akan mengeksekusi tubuh loop kali nol.
sumber
Look Before You Leap lebih disukai dalam hal ini. Dengan pendekatan pengecualian, TypeError dapat terjadi di mana saja di tubuh loop Anda dan itu akan tertangkap dan dibuang, yang bukan yang Anda inginkan dan akan membuat debugging menjadi rumit.
(Saya setuju dengan Brandon Corfman: mengembalikan None untuk 'no items' bukan daftar kosong yang rusak. Ini adalah kebiasaan yang tidak menyenangkan dari coders Java yang tidak boleh dilihat dengan Python. Atau Java.)
sumber
Secara umum, kesan yang saya dapatkan adalah bahwa pengecualian harus disediakan untuk keadaan luar biasa. Jika
result
diharapkan tidak pernah kosong (tetapi mungkin, jika, misalnya, disk macet, dll), pendekatan kedua masuk akal. Di sisi lain, jika sebuah kosongresult
masuk akal dalam kondisi normal, pengujian untuk itu denganif
pernyataan lebih masuk akal.Saya memikirkan skenario (lebih umum):
bukannya yang setara:
sumber
++
tidak berfungsi dalam python, gunakan+= 1
saja.bobince dengan bijak menunjukkan bahwa membungkus case kedua juga dapat menangkap TypeErrors dalam loop, yang bukan yang Anda inginkan. Jika Anda benar-benar ingin menggunakan percobaan, Anda dapat menguji apakah itu dapat dilakukan sebelum loop
Seperti yang Anda lihat, ini agak jelek. Saya tidak menyarankannya, tetapi harus disebutkan untuk kelengkapannya.
sumber
None
, selalu periksa hasilnya denganis None
atauis not None
. Di sisi lain itu juga gaya buruk untuk meningkatkan Pengecualian untuk hasil yang sah. Pengecualian adalah untuk hal-hal yang tidak terduga. Contoh:str.find()
mengembalikan -1 jika tidak ada yang ditemukan, karena pencarian itu sendiri selesai tanpa kesalahan.Sejauh menyangkut kinerja, menggunakan blok try untuk kode yang biasanya tidak meningkatkan pengecualian lebih cepat daripada menggunakan pernyataan if setiap saat. Jadi, keputusan tergantung pada probabilitas kasus pengecualian.
sumber
Sebagai aturan umum, Anda tidak boleh menggunakan try / catch atau pengecualian untuk menangani hal-hal lain untuk mengontrol aliran. Meskipun di balik layar iterasi dikendalikan melalui peningkatan
StopIteration
pengecualian, Anda tetap harus memilih cuplikan kode pertama Anda dari yang kedua.sumber