面向對象高級
isinstance(obj,cls)
檢查obj是否是類 cls 的對象
class Foo(object): pass obj = Foo() print(isinstance(obj, Foo)) 輸出: True
issubclass(sub,super)
檢查sub類是否是 super 類的派生類
class Foo(object): pass class Bar(Foo): pass print(issubclass(Bar, Foo))
b.反射
主要是指程序可以訪問、檢測和修改它本身狀態或行爲的一種能力(自省)
python面向對象中的反射:通過字符串反射到真實的屬性上
面向對象中類中屬性的兩種調用方法:
1. 類名.屬性
2.類名.__dict__[‘屬性名’] #通過字符串的形式
class Foo: x=1 def __init__(self,name): self.name=name def f1(self): print('from f1') print(Foo.x) #方法1Foo.__dict__['x'] #方法2
實現自省的函數,通過操作字符串的方式映射到屬性(適用於類和對象,在python中一切皆對象,類本身也是一個對象)
hasattr(obj,’name’) 判斷obj中有沒有一個name字符串對應的方法或屬性
setattr(x,’y’,’v’) 設置函數,x對象名,y屬性,v值
getattr(x,’y’) 取值函數,x對象名,y屬性
delattr(x,’y’) 刪除函數,x對象名,y屬性
class Ftpserver: def __init__(self,host,port): self.host=host self.port=port def run(self): while True: cmd=input('>>: ').strip() if not cmd:continue # 判斷輸入是否爲空 if hasattr(self,cmd): # 判斷類中是否存在此方法 func=getattr(self,cmd) # 取出該方法的值並賦值給func func() def get(self): print('get func') def put(self): print('put func')
反射的好處:
1.實現可插拔機制:
可以事先把主要的邏輯寫好(只定義接口),然後後期再去實現接口的功能(首先使用hasattr進行判斷是否存在此方法,存在則執行,不存在則跳過)
2.動態導入模塊(基於反射當前模塊成員)
c.item系列
__setitem__ 設置函數
__getitem__ 取值函數
__delitem__ 刪除函數
class Foo: def __getitem__(self, item): print('=====>get') return self.__dict__[item] def __setitem__(self, key, value): print('==============>set') self.__dict__[key]=value # setattr(self,key,value) def __delitem__(self, key): print('============>del') self.__dict__.pop(key) f=Foo() f['x']=123123123123 # 通過f[]的方式對對象進行操作時會調用item方法 print(f['x']) del f['x'] 輸出: ==============>set =====>get 123123123123 ============>del
d.打印對象信息__str__
class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def __str__(self): #在對象被打印時觸發執行 return '<name:%s age:%s sex:%s>' %(self.name,self.age,self.sex) p1=People('egon',18,'male') p2=People('alex',38,'male') print(p1) print(p2)
e.析構方法__del__
當對象在內存中被釋放時,自動觸發執行
注:如果產生的對象僅僅只是python程序級別的(用戶級),那麼無需定義__del__,如果產生的對象的同時還會向操作系統發起系統調用,即一個對象有用戶級與內核級兩種資源,比如(打開一個文件,創建一個數據庫鏈接),則必須在清除對象的同時回收系統資源,這就用到了__del__
典型的應用場景:
創建數據庫類,用該類實例化出數據庫鏈接對象,對象本身是存放於用戶空間內存中,而鏈接則是由操作系統管理的,存放於內核空間內存中,當程序結束時,python只會回收自己的內存空間,即用戶態內存,而操作系統的資源則沒有被回收,這就需要我們定製__del__,在對象被刪除前向操作系統發起關閉數據庫鏈接的系統調用,回收資源
class Foo: def __init__(self,x): self.x=x def __del__(self): #在對象資源被釋放時觸發 print('-----del------') print(self) f=Foo(100000) del f print('=======================>') # 析構方法__del__與文件處理原理差不多: f=open('a.txt') #做了兩件事,在用戶空間拿到一個f變量,在操作系統內核空間打開一個文件 del f #只回收用戶空間的f,操作系統的文件還處於打開狀態 #所以我們應該在del f之前保證f.close()執行,即便是沒有del,程序執行完畢也會自動del清理資源,於是文件操作的正確用法應該是 f=open('a.txt') f.close() # f.close就相當於析構方法__del__,在回收用戶空間的同時回收系統空間
7、異常處理
異常就是程序運行時發生錯誤的信號(在程序出現錯誤時,則會產生一個異常,若程序沒有處理它,則會拋出該異常,程序的運行也隨之終止)
錯誤有兩種:
a.語法錯誤(在語法檢測階段拋出,必須在程序執行前就改正)
b.邏輯錯誤
例如:
TypeError # 類型錯誤 for i in 3: pass NameError # 名稱錯誤 aaaaa ValueError # 值錯誤 int('asdfsadf') IndexError # 索引錯誤 l=[1,2] l[1000] KeyError # key錯誤 d={'a':1} d['b'] AttributeError # 屬性錯誤 class Foo:pass Foo.x
常見異常:
AttributeError 試圖訪問一個對象沒有的樹形,比如foo.x,但是foo沒有屬性x
IOError 輸入/輸出異常;基本上是無法打開文件
ImportError 無法引入模塊或包;基本上是路徑問題或名稱錯誤
IndentationError 語法錯誤(的子類) ;代碼沒有正確對齊
IndexError 下標索引超出序列邊界,比如當x只有三個元素,卻試圖訪問x[5]
KeyError 試圖訪問字典裏不存在的鍵
KeyboardInterrupt Ctrl+C被按下
NameError 使用一個還未被賦予對象的變量
SyntaxError Python 代碼非法,代碼不能編譯(個人認爲這是語法錯誤,寫錯了)
TypeError 傳入對象類型與要求的不符合
UnboundLocalError 試圖訪問一個還未被設置的局部變量,基本上是由於另有一個同名的全局變量,導致你以爲正在訪問它
ValueError 傳入一個調用者不期望的值,即使值的類型是正確的
異常處理
a. 如果錯誤發生的條件是可預知的,我們需要用if進行處理:在錯誤發生之前進行預防
AGE=10 while True: age=input('>>: ').strip() if age.isdigit(): #只有在age爲字符串形式的整數時,下列代碼纔不會出錯,該條件是可預知的 age=int(age) if age == AGE: print('you got it') break
b. 如果錯誤發生的條件是不可預知的,則需要用到try...except:在錯誤發生之後進行處理
異常類只能用來處理指定的異常情況,如果非指定異常則無法處理
try: aaaa # 拋出NameError異常 print('==-==>1') l=[] l[3] # 拋出IndexError異常 print('==-==>2') d={} d['x'] # 拋出KeyError異常 print('==-==>3') # 多分支異常 except NameError as e: print(e) except IndexError as e: print(e) except KeyError as e: print(e) except Exception as e: # 萬能異常,能捕捉到所有的異常 print(e) else: print('在沒有錯誤的時候執行') finally: print('無論有無錯誤,都會執行')
c.主動拋出異常
try: raise TypeError('類型錯誤') except Exception as e: print(e)
d.自定義異常
class EgonException(BaseException): def __init__(self,msg): self.msg=msg def __str__(self): return '<%s>' %self.msg raise EgonException('egon 的異常')
e.斷言
assert