python——面向對象篇之異常和反射

  1. 內置函數isinstance和issubclass

    1.1 isinstance用法:
    1 isinstance(string,str)

     
    判斷第一個參數是不是第二個參數的子集,例如:python

     1 print isinstance("test",str)     #判斷test是不是字符串類型
     2 
     3 C:\Python27\python.exe D:/python/s11/8day/反射/test.py
     4 
     5 True
     6 
     7 
     8 print isinstance(123,int)     #判斷123是不是整型類型
     9 
    10 C:\Python27\python.exe D:/python/s11/8day/反射/test.py
    11 
    12 True
      還能夠判斷對象是否某一個類的實例,返回的是布爾值

    1.2 issubclass用法:
    1 issubclass(sub, super)

      判斷sub是不是super的派生類,返回值也是布爾值數據庫

    注:使用isinstance和issubclass會破壞對象的多態性


  2. 異常處理
         python在遇到錯誤後,會引起異常,若是異常對象並未被處理或者捕捉,則程序就會用所謂的回溯(traceback)來終止程序的執行,以下所示:
    1 C:\Python27\python.exe D:/python/s11/8day/反射/test.py
    2 Traceback (most recent call last):
    3   File "D:/python/s11/8day/test.py", line 26, in <module>
    4     print isinstance(d,int)
    5 NameError: name 'd' is not defined

          在python裏,每一個異常都是類Exception的實例,Exception能夠說是全部異常的基類。若是咱們捉住錯誤並對其處理,那整個程序就不會回溯而是繼續執行下去。

    網絡

     2.1 被動異常
                即把代碼寫在try塊裏,當程序拋錯時自動觸發,except則負責捕捉和處理異常,用法以下併發

    1 try:
    2      代碼塊
    3 except Exception,e:    #e是exception的實例,是一個對象;上面的錯誤信息都封裝在e中
    4      異常處理          #在這裏你能夠打印異常信息,如(print e);也能夠作其餘操做如把異常信息寫入日誌

          在這須要注意的是:若是你print e的時候,由於正常來講print對象時返回的應該是對象的內存地址,而在異常處理這裏,你print對象時會調用exception的__str__方法,將異常信息返回而不是返回內存地址,因此這裏你print的時候會發現顯示的會是異常信息,對此你不須要以爲奇怪。dom


           在except捕獲異常時,你還能夠在except後面再加個except,就像自來水過濾同樣一層層的捕獲特定的異常函數

    1 try:
    2     代碼塊
    3 except KeyError,e:      #試圖訪問字典裏不存在的鍵
    4     print e
    5 except ValueError,e:    #傳入一個調用者不指望的值,即便值的類型是正確的
    6     print e
    7 except Exception,e:     #若是你沒法預期會發生什麼異常,那好,咱們還有個萬能異常
    8     print e

           
             另外一種寫法:測試

    1 try:
    2     Garen = Hero
    3 except (KeyError,ValueError),e:    #寫成元組形式
    4     print e



    2.2 主動觸發異常
               不等程序代碼遇到錯誤拋出後才觸發,而是咱們在預計會出現問題的地方提早觸發     spa

    1 try:
    2     raise Exception('這裏出現錯誤')      #提早傳參並實例化異常
    3 except Exception,e:                    #把錯誤信息封裝到exception的實例e裏
    4     print e


    2.3 自定義異常
               既是咱們本身定義異常的觸發條件和處理方法,建立自定義異常的時候須要直接或者間接的繼承Exception調試

    1 class testError(exception):     //繼承exception異常基類
    2     def __init__(self,msg=None):
    3         self.msg = msg
    4     def __str__(self):
    5         if self.msg:            //根據傳入的參數動態顯示異常信息
    6             return self.msg
    7         else:
    8             return "自定義異常"      //默認異常顯示信息


    調用自定義異常日誌

    1 try:
    2     raise testError()   //實例化自定義異常類,後面括號可傳入參數
    3 except testError,e:
    4     print e

     

    2.4 finally
               無論try子句是否發生異常都會執行,好比當你在讀寫文件或者scoket通信時,不論是否出現異常都應該在結束後關閉文件或者網絡套接字,這時就能夠把關閉方法放在finally子句中

    1 try:
    2     f = open("test.txt","a")
    3     f.write(data)
    4 except Exception,e:
    5     print e
    6 finally:
    7     f.close()

     

    2.5 忽略全部異常
    1 try:
    2     Garen = Hero
    3 except:
    4     pass

         這是一種比較危險的用法,它會忽略程序的全部異常而繼續的讓程序執行下去。


    異常處理只須要記住一點:當咱們知道某段代碼可能會致使某種異常,但咱們又不但願程序中止,那麼咱們就能夠根據須要添加異常處理。

    擴展:反射中的getattr的內部實現也是經過訪問特性並捕捉可引起的AttributeError異常區實現的


  3. 反射
      反射,將名稱轉換成動詞,這是筆者看完《Execution in the Kingdom of Nouns》後對反射的第一反應,你們有興趣能夠去翻閱,一篇不算太長的文章。

          下面咱們來想象一下這麼一個場景:你坐在電腦旁,玩着LOL,經過鼠標和鍵盤傳遞信息,遊戲裏的英雄相應的作出操做,這就能夠當作反射。這是怎麼作到的呢?讓咱們往下看:

    首先咱們定義了一個英雄模板,也就是基類。
     1 class Hero:
     2     def __init__(self):
     3         self.ATK = 30
     4         self.DEF = 10
     5         self.HP = 300
     6         self.MP = 100
     7 
     8     def walk(self):
     9         print "你的英雄正走向目標"
    10     def running(self):
    11         print "你的英雄正跑向目標"
    12     def skills(self):
    13         print "你的英雄正在釋放技能"
    14     def attack(self):
    15         print "你的英雄正在攻擊"

     上面這個英雄基類裏有攻擊、防護、生命和魔法值四個屬性以及走路、跑步、釋放技能和攻擊四個方法動做。

     如今你在電腦前建立了一個角色蓋倫,程序開始把類實例化:

    1 Garen = Hero()

     

     OK,你的英雄角色已經生成了,讓咱們看看蓋倫如今都有什麼(前面四個是屬性,後面四個是方法,中間咱們先無論它):

    1 print dir(Garen)
    2 
    3 C:\Python27\python.exe D:/python/s11/8day/反射/test.py
    4 
    5 ['ATK', 'DEF', 'HP', 'MP', '__doc__', '__init__', '__module__', 'attack', 'running', 'skills', 'walk']

     

     再看看初始屬性是多少(恩,HP比MP高,看來是近戰英雄):

    1 print Garen.__dict__
    2 
    3 C:\Python27\python.exe D:/python/s11/8day/反射/test.py
    4 
    5 {'HP': 300, 'ATK': 30, 'DEF': 10, 'MP': 100}

     

     既然角色生成了,那接下來固然就該開始操做了。你用鼠標對地圖點了一下,一個walk字符串傳到了後臺程序中,如今讓咱們看看程序是怎麼處理的:

    1 if hasattr(Garen,"walk"):       #傳入walk字符串,使用hasattr函數判斷角色是否有該方法
    2     walk = getattr(Garen,"walk")    #若是有則使用getattr函數取出該方法體,但不執行
    3     walk()                       #最後執行該方法

     

    而後你的角色就會作相應的動做:

    1 C:\Python27\python.exe D:/python/s11/8day/反射/test.py
    2 
    3 你的英雄正走向目標

     


          釋放技能也同樣,當你在鍵盤按下技能快捷鍵時把對應技能名稱發給程序,程序把名稱的技能轉換成可執行的動詞執行對應的方法。反射說白了就是把你傳給對象的字符串參數當成對象裏的同名方法去執行,前提是該對象有這個方法。
          固然,反射也不只僅是對象專有,其餘擴展到類、模塊、函數等容器也均可以使用反射,下面就是反射的四個方法:

    1     hasattr():根據輸入參數判斷某個容器中是否有已該參數爲名稱的內容,若是有則返回true
    2     getattr():取出容器中以參數爲名稱的內容
    3     setattr():對容器中以參數爲名稱的內容進行修改
    4     delattr():刪除容器中以參數爲名稱的內容

     

          通常後面兩個比較少用,瞭解便可

  4. 斷言
         斷言是一個比較有意思的東西,它就想一個條件判斷同樣,只有知足時纔會讓程序走下去,否則就報錯。能夠用來檢測系統環境是否知足程序的須要,通常在測試或者調試時使用
    1 assert system == "mac"    #程序只能在mac上執行,若是不知足則不讓執行程序

     

  5. 單例模式

         既是一個類,只實例化一次,只佔用一塊內存,各程序想用這個功能的時候就不用再實例化一個對象,而是調用同一個實例,共享內存。
         舉例:程序會有一個專門鏈接數據庫的類,當用戶查詢數據庫都會實例化一次,建立一個用於鏈接的對象,若是併發大的話會很浪費內存資源,使用單例實例的話就只須要實例化一次,以後你們共用一個鏈接實例,這樣能節省大量資源。

    單例模式類的建立:

     1  1 class Foo(object):
     2  2     __instance = None       #_instance設爲None,代表該類尚未實例化過
     3  3     
     4  4     @staticmethod           #設爲靜態方法
     5  5     def singleton():        
     6  6         if Foo.__instance:      #判斷是否實例化過,若是__instance存在則再也不建立實例,而是直接返回第一次建立的實例
     7  7             return Foo.__instance
     8  8         else:                   
     9  9             Foo.__instance = Foo()      #若是尚未實例化過,則將實例化的對象實例綁定到__instance上,並返回該實例
    10 10             return Foo.__instance

     

    單例模式對象的建立:

    1 obj = Foo.singleton()
相關文章
相關標籤/搜索