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會破壞對象的多態性
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異常區實現的
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 的下載地址:請點這裡