使用斷言表達式,通常會有人誤用它,所以我決定寫一篇文章來說明何時使用斷言,什么時候不用。為那些還不清楚它的人,Python的assert是用來檢查一個條件,如果它為真,就不做任何事。如果它為假,則會拋出AssertError并且包含錯誤信息。例如:pyx=23pyassertx0,"xisnotzeroornegative"pyassertx%2==0,"xisnotanevennumber"Traceback(mostrecentcalllast):File"",line1,inAssertionError:xisnotanevennumber很多人用assert作為一個很快和容易的方法來在參數錯誤的時候拋出異常。但這樣做是錯的,非常錯誤,有兩個原因。首先AssertError不是在測試參數時應該拋出的錯誤。你不應該像這樣寫代碼:ifnotisinstance(x,int):raiseAssertionError("notanint")你應該拋出TypeError的錯誤,assert會拋出錯誤的異常。但是,更危險的是,有一個關于assert的困擾:它可以被編譯好然后從來不執行,如果你用–O或–oo選項運行Python,結果不保證assert表達式會運行到。當適當的使用assert時,這是未來,但是當assert不恰當的使用時,它會讓代碼用-O執行時出錯。那什么時候應該使用assert?沒有特定的規則,斷言應該用于:防御型的編程運行時檢查程序邏輯檢查約定程序常量檢查文檔(在測試代碼的時候使用斷言也是可接受的,是一種很方便的單元測試方法,你接受這些測試在用-O標志運行時不會做任何事。我有時在代碼里使用assertFalse來標記沒有寫完的代碼分支,我希望這些代碼運行失敗。盡管拋出NotImplementedError可能會更好。)關于斷言的意見有很多,因為它能確保代碼的正確性。如果你確定代碼是正確的,那么就沒有用斷言的必要了,因為他們從來不會運行失敗,你可以直接移除這些斷言。如果你確定檢查會失敗,那么如果你不用斷言,代碼就會通過編譯并忽略你的檢查。在以上兩種情況下會很有意思,當你比較肯定代碼但是不是絕對肯定時。可能你會錯過一些非常古怪的情況。在這個情況下,額外的運行時檢查能幫你確保任何錯誤都會盡早地被捕捉到。另一個好的使用斷言的方式是檢查程序的不變量。一個不變量是一些你需要依賴它為真的情況,除非一個bug導致它為假。如果有bug,最好能夠盡早發現,所以我們為它進行一個測試,但是又不想減慢代碼運行速度。所以就用斷言,因為它能在開發時打開,在產品階段關閉。一個非變量的例子可能是,如果你的函數希望在它開始時有數據庫的連接,并且承諾在它返回的時候仍然保持連接,這就是函數的不變量:defsome_function(arg):assertnotDB.closed()#codegoeshereassertnotDB.closed()returnresult斷言本身就是很好的注釋,勝過你直接寫注釋:#whenwereachhere,weknowthatn2你可以通過添加斷言來確保它:assertn2斷言也是一種防御型編程。你不是讓你的代碼防御現在的錯誤,而是防止在代碼修改后引發的錯誤。理想情況下,單元測試可以完成這樣的工作,可是需要面對的現實是,它們通常是沒有完成的。人們可能在提交代碼前會忘了運行測試代碼。有一個內部檢查是另一個阻擋錯誤的防線,尤其是那些不明顯的錯誤,卻導致了代碼出問題并且返回錯誤的結果。加入你有一些if…elif的語句塊,你知道在這之前一些需要有一些值:#targetisexpectedtobeoneofx,y,orz,andnothingelse.iftarget==x:run_x_code()eliftarget==y:run_y_code()else:run_z_code()假設代碼現在是完全正確的。但它會一直是正確的嗎?依賴的修改,代碼的修改。如果依賴修改成target=w會發生什么,會關系到run_w_code函數嗎?如果我們改變了代碼,但沒有修改這里的代碼,可能會導致錯誤的調用run_z_code函數并引發錯誤。用防御型的方法來寫代碼會很好,它能讓代碼運行正確,或者立馬執行錯誤,即使你在未來對它進行了修改。在代碼開頭的注釋很好的一步,但是人們經常懶得讀或者更新注釋。一旦發生這種情況,注釋會變得沒用。但有了斷言,我可以同時對代碼塊的假設書寫文檔,并且在它們違反的時候觸發一個干凈的錯誤asserttargetin(x,y,z)iftarget==x:run_x_code()eliftarget==y:run_y_code()else:asserttarget==zrun_z_code()這樣,斷言是一種防御型編程,同時也是一種文檔。我想到一個更好的方案:iftarget==x:run_x_code()eliftarget==y:run_y_code()eliftarget==z:run_z_code()else:#Thiscanneverhappen.ButjustincaseitdoesraiseRuntimeError("anunexpectederroroccurred")按約定進行設計是斷言的另一個好的用途。我們想象函數與調用者之間有個約定,比如下面的:“如果你傳給我一個非空字符串,我保證傳會字符串的第一個字母并將其大寫。”如果約定被函數或調用這破壞,代碼就會出問題。我們說函數有一些前置條件和后置條件,所以函數就會這么寫:deffirst_upper(astring):assertisinstance(astring,str)andlen(astring)0result=astring[0].upper()assertisinstance(result,str)andlen(result)==1assertresult==result.upper()returnresult按約定設計的目標是為了正確的編程,前置條件和后置條件是需要保持的。這是斷言的典型應用場景,因為一旦我們發布了沒有問題的代碼到產品中,程序會是正確的,并且我們能安全的移除檢查。下面是我建議的不要用斷言的場景:不要用它測試用戶提供的數據不要用斷言來檢查你覺得在你的程序的常規使用時會出錯的地方。斷言是用來檢查非常罕見的問題。你的用戶不應該看到任何斷言錯誤,如果他們看到了,這是一個bug,修復它。有的情況下,不用斷言是因為它比精確的檢查要短,它不應該是懶碼農的偷懶方式。不要用它來檢查對公共庫的輸入參數,因為它不能控制調用者,所以不能保證調用者會不會打破雙方的約定。不要為你覺得可以恢復的錯誤用斷言。換句話說,不用改在產品代碼里捕捉到斷言錯誤。不要用太多斷言以至于讓代碼很晦澀。
成都創新互聯公司自2013年創立以來,是專業互聯網技術服務公司,擁有項目成都網站制作、網站設計、外貿網站建設網站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元古城做網站,已為上家服務,為古城各地企業和個人服務,聯系電話:028-86922220
Python—assert、isinstance的用法
1 assert
assert 語句是一種插入調試斷點到程序的一種便捷的方式。
2 isinstance
當我們定義一個class的時候,我們實際上定義了一種數據類型。
判斷一個變量是否某個類型可以用isinstance()判斷:
class Students():
def init (self,name,score):
self.name = name
self.score = score
a = '10'
b = 3
c = [1,2,3]
d = (1,2,3)
f = Student('Eden',99.9)
print(isinstance(a, str)) # True a屬于字符串
print(isinstance(b, int)) # True b屬于整形
print(isinstance(c, list)) # True c屬于整形
print(isinstance(d, tuple)) # True d屬于元組
print(isinstance(f, Student)) # True f屬于類
3 assert isinstance
a = 2
assert isinstance(a,int) # 插入斷言,判斷a是否為int類型
assertIsNotNone(testValue, message)
定義: 單元測試庫函數,用于單元測試中以檢查輸入值是否為None。
輸入值:
testValue:變量,需要測試的變量。
message:字符串,測試消息失敗時顯示的消息。
返回值: 根據斷言條件返回布爾值,如果輸入值滿足assertIsNotNone()將返回true,否則返回false。
函數名:
1. 判斷是否相等
assertEqual
assertNotEqual
2. 判斷真假
assertTrue
assertFalse
3. 判斷是否為空
assertIsNone
assertIsNotNone
返回值: 滿足斷言,返回True;不滿足斷言,返回False。
當前文章:linux防火墻命令無效,linux即時生效關閉防火墻命令
網址分享:http://m.kartarina.com/article18/hegedp.html
成都網站建設公司_創新互聯,為您提供服務器托管、商城網站、外貿建站、軟件開發、網站改版、網站導航
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯