Python3 與 C# 面向對象之~異常相關
周末多碼文,昨天晚上一篇,今天再來一篇:
在線編程:https://mybinder.org/v2/gh/lotapp/BaseCode/master
在線預覽:http://github.lesschina.com/python/base/oop/3.異常相關.html
代碼褲子:https://github.com/lotapp/BaseCode/tree/master/python/2.OOP/4.Exception
1.異常¶
1.1 try...except¶
又到了開新課的時候了,小明同學這次提前預習了知識,乘著老師還沒來就在黑板上寫下了這段Code:
In [1]:defmain(): try: 1 / 0 # ZeroDivisionError: division by zero except ZeroDivisionError as ex: print(ex) if __name__ == ‘__main__‘: main()
division by zero
1.2 try...except...else...finally¶
小潘同學剛進來就看見了,自語道:“try...except
於是乘著小明上廁所的時候,擦掉小明的Code,自己寫了一段高大上的Code:
In [2]:# 異常捕獲全格式 def test(input_str): try: eval(input_str) except ZeroDivisionError as ex: print("except:", ex) else: print("else:沒有異常就獎勵100塊~") finally:print("finally:小明是傻子~") def main(): test("1/0") print("-" * 10) test("print(‘小明啊小明你調坑裏了~‘)") if __name__ == ‘__main__‘: main()
except: division by zero finally:小明是傻子~ ---------- 小明啊小明你調坑裏了~ else:沒有異常就獎勵100塊~ finally:小明是傻子~
這時候小明和老師一起進來了,同學們隱約間都聽到小明的自誇聲:“老師,我可好了,提前預習並且還寫了個demo在黑板上呢~”
老師一進門看著黑板就笑了,同學們也笑成一片。小明心想,咦~難道我寫錯了?定眼一看黑板,氣呼呼的回座位了
else
可以不寫,不過我們 基本上還是會寫的,畢竟可以知道是真的沒有錯誤,而不是屏蔽了錯誤
1.3 多個異常處理¶
老師很欣慰,覺得這個班真有意思,大家學習空前熱情,為了照顧小明,老師反問道:“有誰知道 多個異常怎麽處理?”
小明飛快的舉手並把黑板上內容擦完,寫下了如下代碼:
In [3]:# 多個異常捕獲 def main(): try: print(xiaopan) # NameError: name ‘xiaopan‘ is not defined 1 / 0 # ZeroDivisionError: division by zero except NameError as ex: print(ex) except ZeroDivisionError as ex: print(ex) if __name__ == ‘__main__‘: main()
name ‘xiaopan‘ is not defined
老師問了小明一聲,有幾個輸出?
小明驕傲的說道:“兩個,我寫了兩個異常處理,當然都執行了”
同學們又笑了,小潘調侃的說了句:“一看就知道去年C#沒好好學,這不都一樣嘛,遇到異常下面代碼還執行嗎?用腦子好好想想”
當我們認為某些代碼可能會出錯時,就可以用try
來運行這段代碼,如果執行出錯,則後續代碼不會繼續執行,而是直接跳轉至except
語句塊,執行完except
後,如果有finally
語句塊,則執行finally語句塊
小明又尷尬了。。。
1.4 多異常簡寫¶
老師再次幫小明圓了個場:“已經很不簡單了,就是最後小得意的時候口誤了,那小明同學你知道Python裏面多異常有個便捷寫法嗎?”
小明趕緊拿起粉筆刷刷刷的寫完,然後說道:“of course”
In [4]:# 多個異常捕獲的簡寫(註意哦,是元組哦) def main(): try: print(xiaopan) # NameError: name ‘xiaopan‘ is not defined 1 / 0 # ZeroDivisionError: division by zero except (NameError, ZeroDivisionError) as ex: print(ex) if __name__ == ‘__main__‘: main()
name ‘xiaopan‘ is not defined
老師趕緊誇了誇小明,心想,哎呦餵終於把這難纏的家夥弄回座位了。
小明走前還不忘說一句:“簡寫的時候註意格式哦,是 元組 不是逗號分隔”
老師這堂課很輕松,大家都預習了而且內容也比較簡單。
接著以提問的方式問道:“小潘同學,你知道異常的基類是什麽嗎?如果要捕獲所有異常該怎麽做呢?”
小潘站起來說道:“是BaseException
”
老師擴充道:“所有的錯誤類型都繼承自BaseException
,所以在使用except
時需要註意的是,它不但捕獲該類型的錯誤,還把其子類也一起捕獲了”
所以一般在捕獲異常的時候 把子類異常放在前面,父類放在後面
看如下代碼:
In [5]:def main(): try: 1 / 0 # ZeroDivisionError: division by zero except BaseException as ex: print("base:", ex) except ZeroDivisionError as ex: print(ex) if __name__ == ‘__main__‘: main()
base: division by zero
如果把父類放第一個,那麽ZeroDivisionError
永遠也不會被執行了,其實你如果裝了 代碼規範提示插件會提示你的
可以參考我之前寫的 vscode設置python3調試環境的擴充部分
來個通用異常捕獲的簡寫(官方不推薦使用簡寫):
In [6]:# 直接except就行了 def main(): try: 1 / 0 dnt += 1 except: print("屏蔽錯誤") if __name__ == ‘__main__‘: main()
屏蔽錯誤
老師繼續講到,我們來看一個場景,現在很多在線編輯器,你在他們那些編輯框裏寫下了代碼也是有異常拋出的,這是怎麽處理的呢?
微軟有開源代碼編輯器比較受歡迎(VSCode的一部分):monaco-editor
提示一下,如果真的要做在線編輯器,記得考慮一下fork炸彈
,這個其實也是很老的東西了,程序員基本上都應該接觸過了
1.5 拋出異常¶
我們繼續,像C#是用thorw
拋出異常,那Python怎麽 捕獲異常後再拋出
呢?怎麽自定義異常
呢?
繼續往下看:
In [7]:# 捕獲異常後再丟出,eg:在線運行的用戶Code def main(): try: 1 / 0 # ZeroDivisionError: division by zero except ZeroDivisionError as ex: print(ex) # 寫個日誌,回頭出問題可以深究 raise if __name__ == ‘__main__‘: main()
division by zero
--------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) <ipython-input-7-15f01346e2d8> in <module>() 9 10 if __name__ == ‘__main__‘: ---> 11main() <ipython-input-7-15f01346e2d8> in main() 2 def main(): 3 try: ----> 41 / 0 # ZeroDivisionError: division by zero 5 except ZeroDivisionError as ex: 6 print(ex) # 寫個日誌,回頭出問題可以深究 ZeroDivisionError: division by zeroIn [8]:
# 拋出自定義異常 class DntException(BaseException): pass def get_age(num): if num <= 0: raise DntException("num must>0") else: print(num) def main(): get_age(-1) get_age(22) # 程序崩了,這句話不會被執行了 if __name__ == ‘__main__‘: main()
--------------------------------------------------------------------------- DntException Traceback (most recent call last) <ipython-input-8-7c9dec6ec225> in <module>() 17 18 if __name__ == ‘__main__‘: ---> 19main() <ipython-input-8-7c9dec6ec225> in main() 12 13 def main(): ---> 14get_age(-1) 15 get_age(22) # 程序崩了,這句話不會被執行了 16 <ipython-input-8-7c9dec6ec225> in get_age(num) 6 def get_age(num): 7 if num <= 0: ----> 8raise DntException("num must>0") 9 else: 10 print(num) DntException: num must>0
異常這一塊基本上講完了(logging
模塊後面會說)有什麽補充的可以說的^_^
1.6 C#異常¶
小明又進行了C#的代碼轉換,怎麽看都覺得還是C#簡單啊,根本不用說啥,代碼一貼就秒懂了。。。
In [1]:%%script csharp try { Convert.ToInt32("mmd"); } catch (Exception ex) { // Input string was not in a correct format Console.WriteLine(ex.Message); }
Input string was not in a correct format.In [2]:
%%script csharp //拋出自定義異常 try { throw new Exception("出錯了啊"); } catch (Exception ex) { Console.WriteLine(ex.Message); }
出錯了啊
你可以自定義異常類,繼承Exception即可,對了C#裏面也是有finally的
try { throw new Exception("出錯了啊"); //Convert.ToInt32("mmd"); } catch (Exception ex) { // Input string was not in a correct format Console.WriteLine(ex.Message); } finally { Console.WriteLine("finally"); }
現在一些需要finally的地方基本上都被using(){}接管了,所以特定場景會使用
先這樣了
Python3 與 C# 面向對象之~異常相關