一、反射 1 什麼是反射 反射的概念是由Smith在1982年首次提出的,主要是指程式可以訪問、檢測和修改它本身狀態或行為的一種能力(自省)。這一概念的提出很快引發了電腦科學領域關於應用反射性的研究。它首先被程式語言的設計領域所採用,併在Lisp和麵向對象方面取得了成績。 2 python面向對象 ...
一、反射
1 什麼是反射
反射的概念是由Smith在1982年首次提出的,主要是指程式可以訪問、檢測和修改它本身狀態或行為的一種能力(自省)。這一概念的提出很快引發了電腦科學領域關於應用反射性的研究。它首先被程式語言的設計領域所採用,併在Lisp和麵向對象方面取得了成績。
2 python面向對象中的反射:通過字元串的形式操作對象相關的屬性。python中的一切事物都是對象(都可以使用反射)
四個可以實現自省的函數
下列方法適用於類和對象(一切皆對象,類本身也是一個對象)
導入其他模塊,利用反射查找該模塊是否存在某個方法
四種方法使用效果展示:
class BlackMedium: feature='Ugly' def __init__(self,name,addr): self.name=name self.addr=addr def sell_house(self): print('%s 黑中介賣房子啦,傻逼才買呢,但是誰能證明自己不傻逼' %self.name) def rent_house(self): print('%s 黑中介租房子啦,傻逼才租呢' %self.name) b1=BlackMedium('萬成置地','回龍觀天露園') #檢測是否含有某屬性 print(hasattr(b1,'name')) print(hasattr(b1,'sell_house')) #獲取屬性 n=getattr(b1,'name') print(n) func=getattr(b1,'rent_house') func() # getattr(b1,'aaaaaaaa') #報錯 print(getattr(b1,'aaaaaaaa','不存在啊')) #設置屬性 setattr(b1,'sb',True) setattr(b1,'show_name',lambda self:self.name+'sb') print(b1.__dict__) print(b1.show_name(b1)) #刪除屬性 delattr(b1,'addr') delattr(b1,'show_name') delattr(b1,'show_name111')#不存在,則報錯 print(b1.__dict__)
3 為什麼用反射之反射的好處
有倆程式員,一個simon,一個是zhurui,simon在寫程式的時候需要用到zhurui所寫的類,但是zhurui去跟女朋友度蜜月去了,還沒有完成他寫的類,simon想到了反射,使用了反射機制simon可以繼續完成自己的代碼,等zhurui度蜜月回來後再繼續完成類的定義並且去實現simon想要的功能。
總之反射的好處就是,可以事先定義好介面,介面只有在被完成後才會真正執行,這實現了即插即用,這其實是一種‘後期綁定’,什麼意思?即你可以事先把主要的邏輯寫好(只定義介面),然後後期再去實現介面的功能
class FtpClient: 'ftp客戶端,但是還麽有實現具體的功能' def __init__(self,addr): print('正在連接伺服器[%s]' %addr) self.addr=addr
#from module import FtpClient f1=FtpClient('192.168.1.1') if hasattr(f1,'get'): func_get=getattr(f1,'get') func_get() else: print('---->不存在此方法') print('處理其他的邏輯')
好處二:動態導入模塊(基於反射當前模塊成員)
二、 __setattr__,__delattr__,__getattr__
三者用法展示:
##getattr
# class Foo: # x=1 # def __init__(self,y): # self.y=y # # def __getattr__(self, item): # print('執行__getattr__') # # f1=Foo(10) # print(f1.y) # print(getattr(f1,'y')) #len(str) ------>str.__len__() ##delattr # # class Foo: # x=1 # def __init__(self,y): # self.y=y # # def __delattr__(self, item): # print('刪除操作__delattr__') # # f1=Foo(10) # del f1.y # print(f1.x) ##setattr 添加/修改屬性會觸發 class Foo: x=1 def __init__(self,y): self.y=y def __setattr__(self,key,value): print('__setattr__執行') # self.key=value self.__dict__[key]=value f1=Foo(10) print(f1.__dict__) f1.z=2 print(f1.__dict__)
三、包裝標準類型
包裝:python為大家提供了標準數據類型,以及豐富的內置方法,其實在很多場景下我們都需要基於標準數據類型來定製我們自己的數據類型,新增/改寫方法,這就用到了我們剛學的繼承/派生知識 其他的標準類型均可以通過下麵的方式進行二次加工
class List(list): def append(self,p_object): if type(p_object) is str: # self.append(p_object) super().append(p_object) else: print('只能添加字元串類型') def show_middle(self): mid_index=int(len(self)/2) return self[mid_index] # l2=List('hello world') # print(l2,type(l2)) l1=List('helloworld') # print(l1,type(l1)) l1.append(123456) l1.append('sb') print(l1)