原標題:還在 Bug 不斷?不妨試試這 2 個裝X技巧
作者 | luanhz
來源 | 小數志(ID:Datazhi)
程序員每天遇到 bug 就像喝水吃飯一樣稀松平常,關鍵在于怎么高效而不失優雅的面對這些 bug!所以,你還在固執的使用 try……except 嗎?
為了提高程序運行的穩健性,幾乎所有語言都提供了 try……except……用法, Python 也不例外。雖然 try……except……語法能夠確保程序能夠跳過異常代碼片段,無論如何都繼續執行下去,但有時主動的觸發報錯和異常也是一種行之有效的程序員裝X護體方法。
本文主要介紹 Python 中的兩個異常相關的關鍵字:assert 和 raise,前者用于斷言發現潛在異常,后者用于觸發報錯,實際上二者功能有很大相近之處。
Python異常分類
Python內置了數十種Exception/Error類型,例如常見的如下幾種:
IndexError,索引錯誤,例如引用了超出列表長度的索引
KeyError,鍵值錯誤,例如引用了字典中不存在的鍵值
NameError,未聲明錯誤,例如引用了未賦值的對象或變量
SyntaxError,語法錯誤,廣泛存在
Indentati,縮進錯誤,這是Python摒棄花括號而用縮進區分代碼段的特色產物
TypeError,類型錯誤,例如執行數字和字符串相加會引發此類錯誤
這些錯誤很常見,也比較直觀易懂。但有沒有考慮過主動觸發這些錯誤呢?
assert:斷言
assert 一般用于函數和類的內部,在執行具體邏輯前首先對輸入參數和程序執行狀態進行一定的檢查和預判,僅當執行狀態滿足時才繼續執行后續的邏輯,否則斷言條件不滿足,引發后續的提示。
assert 關鍵字基本用法為:
assert"條件判斷", "條件不滿足時輸出的提示信息"
例如,設計一個兩數相除的函數,那么應當在執行相除前檢查:
兩個輸入參數是否為數值型
除數是否不為0
這一條件判斷可用assert完成,并在條件不滿足時優雅的提示報錯:
def div(x, y):
assert isinstance(x, (float, int)) and isinstance(y, (float, int)),
"param `x` and `y` expected to be 'int' or 'float' type"
assert y != 0, "param `y` should not to be exactly `0`"
return x/y
div(1, "2")
---------------------------------------------------------------------------
Asserti Traceback (most recent calllast)
in< module>
----> 1 div(1, "2")
indiv(x, y)
1defdiv(x, y):
2assert isinstance(x, ( float, int)) andisinstance(y, ( float, int)),
----> 3 "param `x` and `y` expected to be 'int' or 'float' type"
4assert y != 0, "param `y` should not to be exactly `0`"
5returnx/y
Asserti: param `x`and`y`expected tobe 'int'or'float'type
由于輸入參數y是字符串類型,斷言失敗,引發斷言錯誤
相較于 try……except……用法,assert 的最大意義在于能夠及時發現程序中未按預期狀態執行的錯誤,這在多人協作 coding 過程中,比 except 更能提供豐富的報錯信息。
raise:觸發異常
實際上,raise 關鍵字的哲學與 assert 是有相通之處的,只不過 assert 包含邏輯判斷和觸發提示信息兩部分內容,而 raise 則只用于手動觸發異常,且一般觸發的是 Python 內置異常類型。某種程度上,raise 的靈活性要比 assert 低,在個人實際使用過程中也幾乎很少用到。
raise關鍵字基本語法為:
raise異常類名稱(描述信息)
例如,仍以實現上述 div 函數功能為例,以 raise 關鍵字執行同樣的斷言功能,則可如下實現:
def div(x, y):
if not isinstance(x, (float, int)) or not isinstance(y, (float, int)):
raise TypeError("param `x` and `y` expected to be 'int' or 'float' type")
if y == 0:
raise ZeroDivisi("param `y` should not to be exactly `0`")
return x/y
div(1, 0)---------------------------------------------------------------------------ZeroDivisi Traceback (most recent calllast) in< module>----> 1 div(1, 0) indiv(x, y)3raiseTypeError( "param `x` and `y` expected to be 'int' or 'float' type")4ify == 0:----> 5 raise ZeroDivisi("param `y` should not to be exactly `0`")6returnx/y
ZeroDivisi: param `y`should nottobe exactly `0`
?
由于除數為0,raise關鍵字觸發異常
以上就是 Python 中這兩個關鍵字的簡單用法,單論其實質功能而言都稱不上是不可或缺,甚至可能會覺得有些雞肋,但不得不說在某些場景下二者其實都還是有用武之地,或許屆時你的代碼也可以如大佬一般:優雅高效,同時略顯裝X!
責任編輯: