歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Python——面向對象篇之異常和反射

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

日期:2017/3/1 9:19:07   编辑:Linux編程

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

1.內置函數isinstance和issubclass

1.1 isinstance用法:

isinstance(string,str)

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

print isinstance("test",str) #判斷test是否是字符串類型

C:\Python27\python.exe D:/python/s11/8day/反射/test.py

True


print isinstance(123,int) #判斷123是否是整型類型

C:\Python27\python.exe D:/python/s11/8day/反射/test.py

True

還可以判斷對象是否某一個類的實例,返回的是布爾值

1.2 issubclass用法:

1 issubclass(sub, super)

判斷sub是否是super的派生類,返回值也是布爾值

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


  • 異常處理
    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的時候會發現顯示的會是異常信息,對此你不需要覺得奇怪。


    在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 主動觸發異常
    不等程序代碼遇到錯誤拋出後才觸發,而是我們在預計會出現問題的地方提前觸發

    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異常區實現的

  • 反射
      反射,將名稱轉換成動詞,這是筆者看完《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():刪除容器中以參數為名稱的內容

    一般後面兩個比較少用,了解即可

  • 斷言
    斷言是一個比較有意思的東西,它就想一個條件判斷一樣,只有滿足時才會讓程序走下去,不然就報錯。可以用來檢測系統環境是否滿足程序的需要,一般在測試或者調試時使用
    1 assert system == "mac"    #程序只能在mac上執行,如果不滿足則不讓執行程序
  • 單例模式

    既是一個類,只實例化一次,只占用一塊內存,各程序想用這個功能的時候就不用再實例化一個對象,而是調用同一個實例,共享內存。
    舉例:程序會有一個專門連接數據庫的類,當用戶查詢數據庫都會實例化一次,創建一個用於連接的對象,如果並發大的話會很浪費內存資源,使用單例實例的話就只需要實例化一次,之後大家共用一個連接實例,這樣能節省大量資源。

    單例模式類的創建:

     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()

下面關於Python的文章您也可能喜歡,不妨看看:

Linux下Python的安裝以及注意事項 http://www.linuxidc.com/Linux/2015-11/124861.htm

Ubuntu 14.04 下安裝使用Python rq模塊 http://www.linuxidc.com/Linux/2015-08/122441.htm

無需操作系統直接運行 Python 代碼 http://www.linuxidc.com/Linux/2015-05/117357.htm

CentOS上源碼安裝Python3.4 http://www.linuxidc.com/Linux/2015-01/111870.htm

《Python核心編程 第二版》.(Wesley J. Chun ).[高清PDF中文版] http://www.linuxidc.com/Linux/2013-06/85425.htm

《Python開發技術詳解》.( 周偉,宗傑).[高清PDF掃描版+隨書視頻+代碼] http://www.linuxidc.com/Linux/2013-11/92693.htm

Python腳本獲取Linux系統信息 http://www.linuxidc.com/Linux/2013-08/88531.htm

在Ubuntu下用Python搭建桌面算法交易研究環境 http://www.linuxidc.com/Linux/2013-11/92534.htm

Python 語言的發展簡史 http://www.linuxidc.com/Linux/2014-09/107206.htm

Python 的詳細介紹:請點這裡
Python 的下載地址:請點這裡

Copyright © Linux教程網 All Rights Reserved