python小白:第十九天
1、 異常概述
異常機制己經成為衡量一門程式語言是否成熟的標準之一,使用異常處理機制的python程式有更好的容錯性,更加健壯。
2、 異常處理機制
python的異常處理機制可以讓程式具有極好的容錯性,讓程式更加健壯。當程式執行出現意外情況時,系統會自動生成error物件來通知程式,從而實現將「業務實現**」和「錯誤處理**」分離,提供更好的可讀性。
2.1 使用try…except捕獲異常
上面**中的「if塊」依然不可表示–一切正常是很抽象的,無法轉換為計算機可識別的**。在這種情形下,python提出了一種假設,如果程式可以順利完成,那就「一切正常」,把系統的業務實現**放在try塊中定義,把所有的異常處理邏輯放在except塊中進行處理,下面是python異常處理機制的語法結構:
如果在執行try塊裡的業務邏輯**時出現異常,系統自動生成乙個異常物件,該異常物件被提交給python直譯器,這個過程被稱為引發異常。
當python直譯器收到異常物件時,會尋找能處理該異常物件的except塊,如果找到合適的except塊,則把該異常物件交給該except塊處理,這個過程被稱為捕獲異常。如果python找不到捕獲異常的except塊,則執行時環境終止,python直譯器也將退出。
不管程式**塊是否處於try塊中,甚至包括except塊中的**,只要執行該**塊時出現了異常,系統總會自動生成乙個error物件。如果程式沒有為這段**定義任何的except塊,則python直譯器無法找到處理該異常的except塊,程式就在此退出,這就是前面看到的例子程式在遇到異常時退出的情形。
上面程式把處理使用者輸入字串的**都放在try塊裡執行,只要使用者輸入的字串不是有效的座標值(包括字母不能正確解析,沒有逗號不能正確解析,解析出來的座標引起陣列越界……),系統就將引發乙個異常物件,並把這個異常物件交給對應的except塊(也就是上面程式中粗體字**塊)處理except塊的處理方式是向使用者提示座標不合法,然後使用continue忽略本次迴圈剩下的**,開始執行下一次迴圈,這就保證了該五子棋遊戲有足夠的容容錯性–使用者可以隨意輸入,程式不會因為使用者輸入不合法而突然退出,程式會向使用者提示輸入不合法,讓使用者再次輸入。
2.2 異常類的繼承體系
當python直譯器接收到異常物件時,如何為該異常物件尋找except塊呢?注意上面程式中except塊的except exception:,這意味著每個except塊都是專門用於處理該異常類及其子類的異常例項。
當python直譯器接收到異常物件後,會依次判斷該異常物件是否是except塊後的異常類或其子類的例項,如果是,python直譯器將呼叫該except塊來處理該異常;否則,再次拿該異常物件和下乙個except塊裡的異常類進行比較。
python異常捕獲流程示意圖如圖所示:
從圖中可以看出,在try塊後可以有多個except塊,這是為了針對不同的異常類提供不同的異常處理方式。當程式發生不同的意外情況時,系統會生成不同的異常物件,python直譯器就會根據該異常物件所屬的異常類來決定使用哪個except塊來處理該異常。
通過在try塊後提供多個except塊可以無須在異常處理塊中使用if判斷異常型別,但依然可以針對不同的異常型別提供相應的處理邏輯,從而提供更細緻、更有條理的異常處理邏輯。
從圖中可以看出,在通常情況下,如果try塊被執行一次,則try塊後只有乙個except塊會被執行,不可能有多個except塊被執行。除非在迴圈中使用了continue開始下一次迴圈,下一次迴圈又重新執行了try塊,這才可能導致多個except塊被執行。
python的所有異常類都從baseexception派生而來,提供了豐富的異常類,這些異常類之間有嚴格的繼承關係,如下圖顯示了python的常見異常類之間的繼承關係。
從圖中可以看出,python的所有異常類的基類是baseexception,但如果使用者要實現自定義異常,則不應該繼承這個基類,而是應該繼承exception類。
baseexception的主要子類就是execption,不管是系統的異常類,還是使用者自定義的異常類,都應該從exception派生。
上面程式,匯入了sys模組,並通過sys模組的ar**列表來獲取執行python程式提供的引數其中sys.ar**[0]通常代表正在執行的python程式名,sys.ar**[l]代表執行程式所提供的第乙個引數,sys.ar**[2]代表執行程式所提供的第二個引數……依此類推。
上面程式針對indexerror、valueerror、arithmeticerror型別的異常,提供了專門的異常處理邏輯。該程式執行時的異常處理邏輯可能有以下幾種情形:
如果在執行該程式時輸入的引數不夠,將會發生索引錯誤,python將呼叫indexerror對應的except塊處理該異常。
如果在執行該程式時輸入的引數不是數字而是字母,將發生數值錯誤,python將呼叫valueerror對應的except塊處理該異常。
如果在執行該程式時輸入引數是0,將發生除0異常,python將呼叫arithmeticerror對應的except塊來處理該異常。
如果在程式執行時出現其他異常,該異常物件總是exception類或其子類的例項,python將呼叫exception對應的except塊處理該異常。
程式總是把對應exception類的except塊放在最後,如果excepton類對應的except塊排在其他except塊的前面,python直譯器將直接進入該except塊(因為所有異常物件都是exception或其子類的例項),而排在它後面的except塊將永遠不會獲得執行的機會。
實際上,在進行異常捕獲時不僅應該把exception類對應的except塊放在最後,而且所有父類異常的except塊都應該放在在子類異常的except塊的後面,(即:先處理小異常,再處理大異常)。
2.3 多異常捕獲
python的乙個except塊可以捕獲多種型別的異常。
在使用乙個except塊捕獲多種型別的異常時,只要將多種異常類用圓括號括起來,中間用逗號隔開即可–其實就是構建多個異常類的元組。
上面程式中使用了(indexerror,valueerror, arithmeticerror)來指定所捕獲異常型別,這就表明該except塊可以同時捕獲這三種型別的異常。
倒數第二行**只有except關鍵字,並未指定具體要捕獲的異常型別,這種省略異常類的except語句也是合法的,它表示可捕獲所有型別的異常,一般會作為異常捕獲的最後乙個except塊。
2.4 訪問異常資訊
如果程式需要在except塊中訪問異常物件的相關資訊,則可通過為異常物件宣告變數來實現。當python直譯器決定呼叫某個except塊來處理該異常物件時,會將異常物件賦值給except塊後的異常變數,程式即可通過該變數來獲得異常物件的相關資訊。
所有的異常物件都包含了如下幾個常用屬性和方法。
args:該屬性返回異常的錯誤編號和描述字串。
errno:該屬性返回異常的錯誤編號。
strerror:該屬性返回異常的描述字串。
with_traceback():通過該方法可處理異常的傳播軌跡資訊。
從上面程式可以看出,如果要訪問異常物件,只要在單個異常類或異常類元組(多異常捕獲)之後使用as再加上異常變數即可。
上面程式為異常處理流程新增了else塊,當程式中的try塊沒有出現異常時,程式就會執行else塊。
python的異常處理使用else塊絕不是多餘的語法,當try塊沒有異常,而else塊有異常時,就能體現出else塊的作用了。
上面程式中定義了乙個else_test()函式,該函式在執行時需要接收使用者輸入的引數,隨著使用者輸入資料的不同可能導致異常。接下來程式定義了right_main()、wrong_main()兩個函式,其中right_main()將else_test()函式放在else塊內;而wrong_main()將else_test()函式放在try塊**的後面。
當try塊和else塊都沒有異常時,將else_test()函式放在try塊的**的後面和放在else塊中沒有任何區別。
但如果使用者輸入的資料讓else_test()函式出現異常(try塊依然沒有任何異常),此時程式就會產生如下輸出結果:
對比上面兩個輸出結果,使用者輸入的都是0,這樣都會導致else_test()函式出現異常。如果將else_test()函式放在try塊的**的後面,此時else_test()函式執行產生的異常將會被try塊對應的except塊捕獲,這正是python異常處理機制的執行流程。但如果將else_test()函式放在else塊中,當else_test()函式出現異常時,程式沒有except塊來處理該異常,該異常將會傳播給python直譯器,導致程式中止。
對比上面兩個輸出結果,不難發現,放在else塊中的**所引發的異常不會被except塊捕獲。如果希望某段**的異常能被後面except塊捕獲,那麼就應該將這段**放在try塊的**之後,如果希望某段的異常能向外傳播(不被except塊捕獲),那麼就應該將這段**放在else塊中。
冥想第十九天
不能怪自己多心,畢竟出現不舒服的感覺是因為大腦太關切自己的身體了。一點也不想讓它受刺激。今天出來玩了,早上做了體檢。又帶著小妞妞出來打了預防針,後又跟著朋友出來滎陽南嶺玩了,到時有點困,告訴自己要接受,好好接受當下 但不反抗,知道是正常的。坐上車後睡了一會,所有的精力都回來了。當和朋友一起回來的時候...
ACM 第十九天
積性函式o n 線性篩,篩素數,u n 尤拉函式 n n 1 vis 0 vis 1 1,mu 1 1,phi 1 1 2 for rg int i 2 i n i 7else mu k mu i phi k phi i phi prime j 8 9 可以發現,線性篩分為3部分 1.n本身是素數,...
設計模式學習第十九天
命令模式 模式是從 中而來的,就是 的靈活的排列組合,模式不應為了講清的特設環境而迷惑,而要實踐,最好的就是專案,沒有專案之前就是敲 提高沒有捷徑,就是敲 我對命令特設環境的思路 烤肉者儲存乙個命令的引用,主要作用就是執行繼承父類的子類的命令的執行,依靠遍歷服務員過來的集合進行按個執行 服務員類利用...