標籤:

Python等語言為什麼要引入異常機制,異常機制在編程中有哪些精彩的應用?


那個,,Valid Number 這道題我的代碼

class Solution:
# @param s, a string
# @return a boolean
def isNumber(self, s):
try:
n = float(s)
except:
return False
else:
return True


每當在運行時檢測到程序錯誤時,python就會引發異常。對待異常有兩種方法:一是可以在程序中捕捉和響應錯誤;或者忽略已發生的異常。

如果是忽略已發生的異常,python默認的異常處理行為將啟動:停止程序,列印出錯消息。如果不想啟動這種默認行為,就要寫try語句來捕捉異常並從異常中恢復,當程序運行檢測到錯誤時,python會跳到try處理器,而程序在try之後會重新繼續執行。

首先來看看python自帶的默認異常處理器

def fetcher(obj, index):
return obj[index]

x = spam

print(fetcher(x,3))
print(fetcher(x,9))

m
Traceback (most recent call last):
File "E:/12homework/12homework.py", line 7, in &
print(fetcher(x,9))
File "E:/12homework/12homework.py", line 2, in fetcher
return obj[index]
IndexError: string index out of range

從這個例子可以看到,我們試圖對字元串末尾以後的位置做索引運算,當函數嘗試執行obj[9]時,就會觸發異常。Python會替序列檢測到超出邊界的索引運算,並通過拋出(觸發)內置的IndexError異常進行報告。

在這個例子中,我們的代碼沒有刻意去捕捉這個異常,所以他會一直向上返回到程序頂層,並啟用默認的異常處理器:就是列印標準出錯信息,即異常發生時激活的程序行和函數清單。

那麼,如果我們想自己去捕獲異常呢?

因為在有些情況下,這並不是我們想要的。例如,伺服器程序一般需要在內部發生錯誤時依然保持繼續工作。如果你不想要默認的異常行為,就需要把調用封裝在try語句內,自行捕捉異常。

def fetcher(obj, index):
return obj[index]

x = spam

try:
fetcher(x,9)
except IndexError:
print(got exception)

got exception

現在,當try代碼塊內程序執行觸發異常時,python會自動跳至處理器(即except分句下面的代碼塊)去運行。

def fetcher(obj, index):
return obj[index]

x = spam

try:
fetcher(x,9)
except IndexError:
print(got exception)
print(continue...)

got exception
continue...

在這個例子中,我們在異常捕捉和處理後,程序在捕捉了整個try語句後繼續執行;這就是我們之所以得到continue消息的原因。我們沒有看見標準出錯信息,而程序也將正常執行下去。

除了python自身會產生異常以外,我們在程序中也可以主動引發異常。想要手動觸發異常,可以直接執行raise語句。用戶通過raise觸發的異常的捕捉方式和python程序自身引發的異常一樣:

try:
raise IndexError
except IndexError:
print(got exception)

got exception

如果沒有去捕捉到異常,用戶定義的異常就會向上傳遞,直到頂層默認的異常處理器,並通過標準出錯信息終止該程序,看看,是不是感覺很熟悉。

raise IndexError

Traceback (most recent call last):
File "E:/12homework/12homework.py", line 1, in &
raise IndexError
IndexError

我們還可以自定義異常

剛才我們利用raise語句觸發了python內置作用域中定義的一個內置異常。其實我們也可以自己定義一個新的異常,這裡可能需要一點面向對象的知識,所以我們只需要了解即可:自定義的異常能夠通過類來編寫,它繼承自一個內置的異常類:通常這個類的名稱叫做Exception

class Bad(Exception):
pass

def doomed():
raise Bad()

try:
doomed()
except Bad:
print(got Bad)

got Bad

最後說說終止行為finally代碼塊

try語句可以包含finally代碼塊。可以定義一定會在最後執行時的收尾行為。這裡的「一定「指的是無論try代碼塊中是否發生了異常都會執行。

try:
raise IndexError
finally:
print(in finally)
print(after finally)

in finally
Traceback (most recent call last):
File "E:/12homework/12homework.py", line 2, in &
raise IndexError
IndexError

try:
print(ok)
finally:
print(in finally)
print(after finally)

ok
in finally
after finally

可以看出,上述try/finally語句組合,無論try代碼塊是否發生異常,程序都將會執行finally代碼塊中的語句。但是當有異常發生時,python會跳過去執行finally中的行為,執行完finally中的語句後,再將try中的異常傳遞給頂層的默認處理器,因此finally後面的語句就不會執行了。但是如果try中的代碼不觸發異常,則finally後面的代碼塊就會正常的繼續執行。

我們總結一下:

在實際應用中,try/except的組合可用於捕捉異常並從中恢復,而try/finally的組合則很方便,可以確保無論try代碼塊內的代碼是否發生了異常,終止行為都一定會運行。

一個例子是:比如無論是否出現異常,無論異常是否被捕獲,都一定會確保關閉文件。

最終我們是可以把try/except/finally三者連用的,try內為主體功能代碼,except用來捕獲異常,而無論異常是否出現,是否被except捕獲,都將執行finally內的語句。

關於數據科學更系統、更深入的探討可進入我們的專欄《Python數據科學之路》:

醬油哥:來吧,一起踏上Python數據科學之路?

zhuanlan.zhihu.com圖標

本專欄模仿美劇劇集編排分為五季,第一季:Python編程語言核心基礎、第二季:Python數據分析基本工具、第三季:Python語言描述的數學基礎、第四季:機器學習典型演算法專題、第五季:實戰熱點深度應用。


推薦閱讀:

學習Python之前需要先學習一下c語言嗎?
python應該怎麼記各種函數名?
Python是真的火,還是炒的火?
.py怎麼轉換成exe格式!?
自學python一年能找著怎樣的工作啊?

TAG:Python | 編程 |