https://zhuanlan.zhihu.com/p/91853234
什么是assert斷言
Assert statements are a convenient way to insert debugging assertions into a program
斷言聲明是用於程序調試的一個便捷方式。斷言可以看做是一個debug工具,Python的實現也符合這個設計哲學,在Python中assert語句的執行是依賴於__debug__這個內置變量的,其默認值為True。當__debug__為True時,assert語句才會被執行。
對於一般的聲明,assert expression等價於
if __debug__:
if not expression: raise AssertionError
assert可以同時聲明兩個expression,例如assert expression1, expression2等價於
if __debug__:
if not expression1: raise AssertionError(expression2)
如果執行腳本文件時加上-O參數, __debug__則為False
舉一個例子,假設我們有一個腳本testAssert.py,內容為:
print(__debug__)
assert 1 > 2
當使用python assert.py運行時,__debug__會輸出True,assert 1 > 2語句會拋出AssertionError異常。
當使用python -O assert.py運行時,__debug__會輸出False,assert 1 > 2語句由於沒有執行不會報任何異常。
斷言和異常的使用場景
先說結論:
檢查先驗條件使用斷言,檢查后驗條件使用異常
舉個例子來說明一下,在開發中我們經常會遇到讀取本地文件的場景。我們定義一個read_file方法。
def read_file(path):
assert isinstance(file_path, str)
...
read_file函數要求在開始執行的時候滿足一定條件:file_path必須是str類型,這個條件就是先驗條件,如果不滿足,就不能調用這個函數,如果真的出現了不滿足條件的情況,證明代碼中出現了bug,這時候我們就可以使用assert語句來對file_path的類型進行推斷,提醒程序員修改代碼,也可以使用if...raise...語句來實現assert,但是要繁瑣很多。在很多優秀的Python項目中都會看到使用assert進行先驗判斷的情況,平時可以多多留意。
read_file函數在被調用執行后,依然需要滿足一定條件,比如file_path所指定的文件需要是存在的,並且當前用戶有權限讀取該文件,這些條件稱為后驗條件,對於后驗條件的檢查,我們需要使用異常來處理。
def read_file(file_path):
assert isinstance(file_path, str)
if not check_exist(file_path):
raise FileNotFoundError()
if not has_privilege(file_path):
raise PermissionError()
文件不存在和沒有權限,這兩種情況並不屬於代碼bug,是代碼邏輯的一部分,上層代碼捕獲異常后可能會執行其他邏輯,因此我們不能接受這部分代碼在生產環境中被忽略,這屬於后驗條件。並且,相比於assert語句只能拋出AssertionError,使用異常可以拋出更詳細的錯誤,方便上層代碼針對不同錯誤執行不同的邏輯。