day25 Pyhton學習 約束和異常處理

一.類的約束java

  約束是對類的約束python

  有兩種方法:程序員

  1.提取一個父類,在父類中給出一個方法,而且在方法中不給出任何代碼,直接拋異常函數

class Base:
   def login(self):
     raise Exception("你沒有實現login方法()")
class Normal(Base):
   def login(self):
     pass
class Member(Base):
   def denglu(self):
     pass
class Admin(Base):
   def login(self):
     pass

# 項目經理寫的總入口 def login(obj):   print(
"準備驗證碼.......")   obj.login()   print("進入主頁.......")

n
= Normal() m = Member() a = Admin() login(n) login(m) # 報錯. login(a)
在執行到login(m)的時候程序會報錯. 緣由是, 此時訪問的login()是父類中的方法. 可是父類中的方法會拋出一個異常. 因此報錯. 這樣程序員就不得不寫login方法了. 從而對子類進行了相應的約束.
在本示例中. 要注意. 咱們拋出的是Exception異常. 而Exception是全部異常的根. 咱們沒法經過這個異常來判斷出程序是由於什麼報的錯. 因此. 最好是換一個比較專業的錯誤信息. 最好是換成NotImplementError. 其含義是. "沒有實現的錯誤". 這樣程序員或者項目經理能夠一目瞭然
的知道是什麼錯了. 就比如. 你犯錯了. 我就告訴你犯錯了. 你也不知道哪裏錯了. 這時我告訴你, 你xxx錯了. 你改也好改不是?

  2.寫抽象類和抽象方法,這種方案相對來講比上一個麻煩一些.須要你們先引入一個抽象的概念,咱們若是寫一個方法,不知道方法的內部應該到底寫什麼,那這個方法就應該是一個抽象方法,若是一個類包含抽象方法,那麼這個類必定是一個抽象類.抽象類是不能有測試

實例的spa

 

在python中編寫一個抽象類比較麻煩. 須要引入abc模塊中的ABCMeta和abstractmethod這兩個內容. 來咱們看一個例子.
from abc import ABCMeta, abstractmethod
# 類中包含了抽象方法. 那此時這個類就是個抽象類. 注意: 抽象類能夠有普通方法
class IGame(metaclass=ABCMeta):
     # 一個遊戲到底怎麼玩兒? 你能形容? 流程能同樣麼?
     @abstractmethod
     def play(self):
          pass
     def turn_off(self):
          print("破B遊戲不玩了, 脫坑了")
class DNFGame(IGame):
     # 子類必須實現父類中的抽象方法. 不然子類也是抽象類
     def play(self):
         print("dnf的玩兒法")
# g = IGame() # 抽象類不能建立對象
dg = DNFGame()
dg.play()
經過代碼咱們能發現. 這裏的IGame對DNFGame進行了約束. 換句話說. 父類對子類進行了約束    
接下來. 繼續解決咱們一開始的問題.
from abc import ABCMeta, abstractmethod
class Base(metaclass=ABCMeta):
     @abstractmethod
     def login(self):
            pass
class Normal(Base):
     def login(self):
         pass
class Member(Base):
     def denglu(self): # 這個就沒用了
             pass
     def login(self): # 子類對父類進行實現
             pass
class Admin(Base):
     def login(self):
             pass
# 項目經理寫的總入口
def login(obj):
     print("準備驗證碼.......")
     obj.login()
     print("進入主頁.......")
n = Normal()
m = Member()
a = Admin()
login(n)
login(m)
login(a)

 總結: 約束. 其實就是父類對子類進行約束. 子類必需要寫xxx方法. 在python中約束的方式和方法有兩種:
        1. 使用抽象類和抽象方法, 因爲該方案來源是java和c#. 因此使用頻率仍是不多的
        2. 使用人爲拋出異常的方案. 而且儘可能拋出的NotImplementError. 這樣比較專業, 並且錯誤比較明確.(推薦)

二.異常處理調試

  什麼是異常?異常是程序在運行過程當中產生的錯誤,若是程序出現了異常,怎麼處理呢?code

def chu(a, b):
         return a/b
try:
     ret = chu(10, 0)
     print(ret)
except Exception as e:
      print("除數不能是0")
結果:
除數不能是0
     那try...except是什麼意思呢? 嘗試着運行xxxxx代碼. 出現了錯誤. 就執行except後面的代碼. 在這個過程當中. 當代碼出現錯誤的時候. 系統會產生一個異常對象. 而後這個異常會向外拋. 被except攔截. 並把接收到的異常對象賦值給e. 這裏的e就是異常對象. 那這裏的
Exception是什麼?Exception是全部異常的基類, 也就是異常的跟. 換句話說. 全部的錯誤都是Exception的子類對象. 咱們看到的ZeroDivisionError 其實就是Exception的子類. 那這樣寫好像有點問題. Exception表示全部的錯誤. 太籠統了. 全部的錯誤都會被認爲是Exception.
當程序中出現多種錯誤的時候, 就很差分類了, 最好是出什麼異常就用什麼來處理. 這樣就更加合理了.因此在try...execpt語句中. 還能夠寫更多的except.

給出一個完整的異常處理方法(語法):orm

try:
 '''操做'''
except Exception as e:
 '''異常的父類,能夠捕獲全部的異常'''
else:
 '''保護不拋出異常的代碼, 當try中無異常的時候執⾏'''
finally:
 '''最後老是要執行我'''

解讀: 程序先執行操做, 而後若是出錯了會走except中的代碼. 若是不出錯, 執行else中的代碼. 不論出不出錯. 最後都要執行finally中的語句. 通常咱們用try...except就夠用了. 頂多加上finally. finally通常用來做爲收尾工做.對象

def add(a, b):
     '''
      我傳遞兩個整數. 我幫你計算兩個數的和
     :param :param a:
     :param :param b:
     :return :return:
     '''
     if not type(a) == int and not type(b) == int:
     # 當程序運行到這句話的時候. 整個函數的調用會被中斷. 並向外拋出一個異常.
             raise Exception("不是整數, 朕不能幫你搞定這麼複雜的運算.")
     return a + b
# 若是調用方不處理異常. 那產生的錯誤將會繼續向外拋. 最後就拋給了用戶
# add("你好", "我叫賽利亞")
# 若是調用方處理了異常. 那麼錯誤就不會丟給用戶. 程序也能正常進行
try:
     add("胡辣湯", "滋滋冒油的大腰子")
except Exception as e:
     print("報錯了.本身處理去吧")

當程序運行到raise. 程序會被中斷. 並實例化後面的異常對象. 拋給調用方. 若是調用方不處理. 則會把錯誤繼續向上拋出. 最終拋給用戶. 若是調用方處理了異常. 那程序能夠正常的進行執行.

自定義異常: 很是簡單. 只要你的類繼承了Exception類. 那你的類就是一個異常類. 就這麼簡單.

# 繼承Exception. 那這個類就是一個異常類
class GenderError(Exception):
         pass
class Person:

     def __init__(self, name, gender):
         self.name = name
         self.gender = gender

def nan_zao_tang_xi_zao(person):
     if person.gender != "":
         raise GenderError("性別不對. 這裏是男澡堂⼦")
p1 = Person("alex", "")
p2 = Person("eggon", "")

# nan_zao_tang_xi_zao(p1)
# nan_zao_tang_xi_zao(p2) # 報錯. 會拋出一個異常: GenderError

# 處理異常
try:
     nan_zao_tang_xi_zao(p1)
     nan_zao_tang_xi_zao(p2)
except GenderError as e:
     print(e) # 性別不對, 這裏是男澡堂子
except Exception as e:
     print("反正報錯了")

若是是真的報錯了. 咱們在調試的時候, 最好是能看到錯誤源自於哪裏? 怎麼辦呢? 須要引入另外一個模塊traceback. 這個模塊能夠獲取到咱們每一個方法的調用信息. 又被成爲堆棧信息. 這個信息對咱們拍錯是頗有幫助的.

import traceback
# 繼承Exception. 那這個類就是一個異常類
class GenderError(Exception):
      pass
class Person:
  def __init__(self, name, gender):
     self.name = name
     self.gender = gender
def nan_zao_tang_xi_zao(person):
 if person.gender != "":
    raise GenderError("性別不對. 這裏是男澡堂子")
p1 = Person("alex", "")
p2 = Person("eggon", "")
# nan_zao_tang_xi_zao(p1)
# nan_zao_tang_xi_zao(p2) # 報錯. 會拋出一個異常: GenderError
# 處理異常
try:
  nan_zao_tang_xi_zao(p1)
  nan_zao_tang_xi_zao(p2)
except GenderError as e:
  val = traceback.format_exc() # 獲取到堆棧信息
  print(e) # 性別不對. 這裏是男澡堂子
  print(val)
except Exception as e:
  print("反正報錯了")
#性別不對. 這裏是男澡堂子
Traceback (most recent call last):
  File "D:/python_qishi/day021練習/練習.py", line 66, in <module>
    nan_zao_tang_xi_zao(p2)
  File "D:/python_qishi/day021練習/練習.py", line 58, in nan_zao_tang_xi_zao
    raise GenderError("性別不對. 這裏是男澡堂子")
GenderError: 性別不對. 這裏是男澡堂子

當測試代碼的時候把堆棧信息打印出來. 可是當到了線上的生產環境的時候把這個堆棧去掉便可.

相關文章
相關標籤/搜索