天天看點

python基礎(part14)--異常處理

鄙人學習筆記

開發工具:Spyder

文章目錄

  • ​​異常處理​​
  • ​​異常​​
  • ​​異常處理​​
  • ​​舉個例子1​​
  • ​​舉個例子2​​
  • ​​raise語句​​
  • ​​案例​​
  • ​​自定義異常​​
  • ​​案例​​

異常處理

我們先以一個例子為開頭

代碼:

python基礎(part14)--異常處理

控制台輸入5,則正常運作:

python基礎(part14)--異常處理

但如果我們輸入xxx, 那麼回怎樣呢:

python基礎(part14)--異常處理

python會報錯!出現ValueErroe錯誤.

如果我們輸入0,有會怎樣呢:

python基礎(part14)--異常處理

python又報錯了!出現ZeroDivisionErroe錯誤

備注:如果代碼出現錯誤,那麼發生錯誤之後的代碼,則不會運作(”後續邏輯…….”沒有被列印)

異常

  • 定義

異常就是運作時檢測到的錯誤(在有些語言中,比如JAVA,錯誤和異常是有明确差別的. 但在python中異常和錯誤的界定不清晰, 我們則可以說錯誤是一種異常)。

  • 現象

當運作時,程式不會再向下執行,而轉到函數的調用語句。

比如:

python基礎(part14)--異常處理
  • 常見的異常類型

名稱異常(NameError):變量未定義。

類型異常(TypeError):不同類型資料進行運算。

索引異常(IndexError):超出索引範圍。

屬性異常(AttributeError):對象沒有對應名稱的屬性。

鍵異常(KeyError):沒有對應名稱的鍵。

為實作異常(NotImplementedError):尚未實作的方法。

備注:Exception類為異常基類,是其他所有異常類的父類.

異常處理

為了不讓異常影響到之後的程式運作,我們就需要進行異常的處理,“讓異常變為正常”。

  • 文法
try:
    可能觸發異常的語句
except 錯誤類型1 [as 變量1]:
    處理語句1
except 錯誤類型2 [as 變量2]:
    處理語句2
except Exception  [as 變量3]:
    不是以上錯誤類型的處理語句
else:
    未發生異常的語句
finally:
無論是否發生異常的語句      
  • 作用

将程式由異常狀态轉為正常流程。

  • 說明
子句 含義
as子句 是用于綁定錯誤對象的變量,可以忽略
except子句 該子句可以有一個或多個,用來捕獲某種類型的錯誤
else子句 該子句最多隻能有一個
finally子句 該子句最多隻能有一個,如果沒有except子句,該子句就必須存在

舉個例子1

代碼:

python基礎(part14)--異常處理

異常處理:

python基礎(part14)--異常處理

運作, 并在控制台輸入​

​ss​

​:

python基礎(part14)--異常處理

由結果可知,經過異常處理後,我們将發生的異常列印的出來,并執行了後面的代碼。

如果我們修改一下處理語句,如下所示:

python基礎(part14)--異常處理

運作一下, 并在控制台先輸入​

​xx​

​​, 異常被處理後,再故意輸入​

​ff​

​:

python基礎(part14)--異常處理

結果會怎樣呢?

python基礎(part14)--異常處理

會報錯!這是因為當​

​person_count = int(input(“請輸入人數:”))​

​​語句又發生異常時,它找回了調用它的語句​

​div_apple(10)​

​(注意:是except下的​

​div_apple(10)​

​),python發現并沒有 try-except的異常處理語句幫他處理,于是他就報錯了。

Exception類可以捕獲到所有類型的異常。但是如果隻寫它,我們就不能對具體錯誤,做出相應的處理邏輯。

如果我們再修改一下處理語句,如下所示:

python基礎(part14)--異常處理

我們試着運作一下, 并在控制台輸入​​

​0​

​​:

python基礎(part14)--異常處理

我們再運作一下, 并在控制台輸入​​

​af​

​:

python基礎(part14)--異常處理

這樣我們就可以對症下藥,對具體錯誤,做出相應的處理。

但是,我們可能不會預測到所有會發生的錯誤。這時,我們就可以,在末尾加一個Exception捕獲剩餘錯誤。

我們修改一下處理語句:

python基礎(part14)--異常處理

這樣就可以既做到對症下藥,又做到面面俱到。

舉個例子2

我們在處理語句中增加一個else(當沒有發生異常時,執行的語句):

python基礎(part14)--異常處理

我們再運作一下, 并在控制台輸入​

​4​

​:

python基礎(part14)--異常處理

除此之外,還有一個關鍵字finally(不管有沒有異常都執行), 我們測試一下:

python基礎(part14)--異常處理

我們先在控制台輸入一個有錯的​

​f​

​​:

python基礎(part14)--異常處理

我們再在控制台輸入一個沒錯的​

​4​

​:

python基礎(part14)--異常處理

但是我們要是把print(“無論是否發生異常, 都執行的邏輯”)寫在處理異常的語句之外(詳見下圖),這句話也可以執行,那麼這個finally到底有啥用呢?

python基礎(part14)--異常處理

請聽下回分解!

raise語句

  • 作用

抛出一個錯誤,讓程式進入異常狀态。

  • 目的

在程式調用層數較深時,向主函數傳遞錯誤資訊要層層retrun比較麻煩(或者幹脆就不能寫return)。是以,可以人為抛出異常,直接傳遞錯誤資訊。

  • 圖示

假如我們有一個方法fun01,它調用了方法fun02, fun02調用了方法fun03, fun03調用了方法fun04。當我們想用fun04向fun01傳遞一個資訊時,可以層層return,一層一層的傳遞資料:

python基礎(part14)--異常處理

但是我們也可以用fun04人為抛出一個異常,直接把資訊傳遞給fun01:

python基礎(part14)--異常處理

案例

我們建立一個Bunny類,如果建立的Bunny對象的age不符合,大于等于0且小于等于5的要求,我們就抛出異常。

代碼:

class Bunny:
    __slots__ = ("__age")
    def __init__(self, age):
        self.age = age
        
    @property
    def age(self):
        return self.__age
    
    @age.setter
    def age(self, value):
        if 0 <= value <= 5:
            self.__age = value
        else:
            raise ValueError("非幼年")

try:
    b01 = Bunny(6)
    print(b01.age)

except Exception as e:
    print(e)      

結果:

python基礎(part14)--異常處理

自定義異常

如果python提供的異常類型,并不滿足我們的需求,我們就可以自定義異常。

  • 文法

定義自定義異常:

class 類名Error(Exception):
    def __init__(self,參數):
      super().__init__(參數)
      self.資料 = 參數      

調用自定義異常:

try:
    ...
    raise 自定義異常類名(參數)
    ...
except 定義異常類 as 變量名:
    變量名.資料      
  • 作用

封裝錯誤資訊

案例

我們在上面一個案例中借用了ValueError異常類型,人為抛出異常,但是我們覺得,并不能滿足我們的需求,我們想自己建立一個專用的異常類,抛出錯誤資訊。

建立異常類:

class AgeError(Exception):
    
    def __init__(self, msg, age_value):
        super().__init__(msg)
        self.age_value = age_value      

備注:msg表示錯誤的資訊[這是一定要傳的參數,并且要傳給父類的構造方法], 我們還可以自己傳一些想傳遞的資訊,比如:age_value錯誤的年齡

調用自定義異常類:

class Bunny:
    __slots__ = ("__age")
    def __init__(self, age):
        self.age = age
        
    @property
    def age(self):
        return self.__age
    
    @age.setter
    def age(self, value):
        if 0 <= value <= 5:
            self.__age = value
        else:
            raise AgeError("非幼年", value)      
try:
    b01 = Bunny(6)
    print(b01.age)

except AgeError as e:
    print(e.args)
    print(e.age_value)