不用try也可以優(yōu)雅的處理異常
Pythonista[1]們都知道使用 try 和 except 來(lái)處理可能發(fā)生的異常,當(dāng)異常發(fā)生時(shí)執(zhí)行我們預(yù)先編寫好的代碼塊。
但是常碰到的情形是這樣的:
我們知道這個(gè)異常有可能發(fā)生 我們不關(guān)心這個(gè)異常,如果發(fā)生了,什么也不用處理,直接忽略就好
如果要處理這種情形的異常,那么不必使用 try-except,Python 內(nèi)置的 contextlib 庫(kù)提供了一個(gè)函數(shù),叫 suppress,是處理這種異常更優(yōu)雅的方式,Pythonista 一定要嘗試使用。
假如我們要對(duì)一系列數(shù)字的倒數(shù)求和,這些數(shù)字可能會(huì)出現(xiàn) 0,因此需要處理異常,通常情況下,如果使用 try 和 except 會(huì)是這樣的:
nums?=?[3,0,3,0,3]
result?=?0
for?num?in?nums:
????try:
????????result?+=?1/num
????except?ZeroDivisionError:
????????pass
print(result)?#?1.0
這里,我們捕捉了 ZeroDivisionError 異常并忽略,最終得到數(shù)字的倒數(shù)的和為 1.0。
假如我們使用 contextlib 庫(kù)提供的 suppress,代碼就是這樣的:
from?contextlib?import?suppress
nums?=?[3,0,3,0,3]
result?=?0
for?num?in?nums:
????with?suppress(ZeroDivisionError):
????????result?+=?1/num
print(result)?#?1.0
從形式上看,suppress 的代碼行數(shù)更少,看來(lái)也更優(yōu)雅,更易于閱讀理解。
有人會(huì)說(shuō)了,我使用下面的方法一行就搞定了:
result?=?sum([1/x?for?x?in?nums?if?x?!=?0])
這當(dāng)然是完全正確的,上述只是以這個(gè)為例子說(shuō)明下 suppress 的用法,不過當(dāng)異常類型增多的時(shí)候,上述的方法也有弊端,比如數(shù)字除了不能為 0,也不能為字符串的情況, 那么就需要寫成這樣:
nums?=?[3,0,3,0,3,'3']?#有字符串,也需要忽略
result?=?sum([1/x?for?x?in?nums?if?x?!=?0?and?type(x)?==?int])?
當(dāng)異常的情況不斷增多,這種寫法就很難看了,而使用 suppress,只需要這樣:
for?num?in?nums:
????with?suppress(ZeroDivisionError,?TypeError):
????????result?+=?1/num
甚至,你想忽略所有的異常,只需要給 suppress 傳入異常類的基礎(chǔ)類 Exception 即可:
for?num?in?nums:
????with?suppress(Exception):
????????result?+=?1/num
需要注意的是,不要這樣寫
result?=?0?
nums?=?[3,0,3,0,3]
with?suppress(Exception):
????for?num?in?nums:
????????result?+=?1/num
print(result)?#?0.3333333333333333
如果 suppress 寫在了循環(huán)體的外面,當(dāng)發(fā)生異常時(shí),后面的循環(huán)操作將會(huì)被 break,因此這種情況下,結(jié)果是 0.333333,原因就是第二個(gè)數(shù)是 0 引發(fā)的異常,這個(gè)異常雖然被忽略,但后面的循環(huán)也停止了。這一點(diǎn)不是 suppress 特有的,你把 try 放循環(huán)外面也是一樣的:
result?=?0?
nums?=?[3,0,3,0,3]
try:
????for?num?in?nums:
????????result?+=?1/num
except?Exception:
????pass
????
print(result)?#?0.3333333333333333
本文介紹一種更加優(yōu)雅的異常處理方法,就是 Python 標(biāo)準(zhǔn)庫(kù) contextlib 的函數(shù) suppress 它更加優(yōu)雅和容易理解。如果覺得本文對(duì)你有所幫助,關(guān)注、轉(zhuǎn)發(fā)、在看,一條龍走起,我就當(dāng)你打賞了 66 元了,感謝老鐵。
往期 Python 編程技巧文章推薦
參考資料
Pythonista: 表示「Python支持者」,更表示資深的,對(duì)代碼質(zhì)量和品味有要求的開發(fā)者,這種執(zhí)念也就是所謂「Pythonic」
