Python裝飾器重載內(nèi)置的使用
python2.x的新式類和python3.x的全部類,內(nèi)置操作表達(dá)式調(diào)用,不會觸發(fā)__getattr__()和__getattribute__()。參考《python的getattr和getattribute攔截內(nèi)置操作》。
NO | 內(nèi)置操作表達(dá)式(隱式調(diào)用) | 對應(yīng)方法(顯式調(diào)用) |
---|---|---|
1 | 索引操作[i] | __getitem__ |
2 | 加法(連接)操作+ | __coerce__ __add__ |
3 | 括號調(diào)用() | __call__ |
4 | 打印print() | __str__ |
__coerce__:表示強(qiáng)制類型轉(zhuǎn)換,使用加法(或連接)操作+時(shí),不同類型會觸發(fā)類型轉(zhuǎn)換或者報(bào)錯(cuò)。
內(nèi)置操作調(diào)用方式:隱式調(diào)用,即調(diào)用表達(dá)式;顯式調(diào)用,即調(diào)用方法名。
1.1 Py3內(nèi)置操作表達(dá)式調(diào)用無法委托
描述
內(nèi)置操作的表達(dá)式調(diào)用,無法在python3.0下委托,因?yàn)椴粫|發(fā)__getattr__()和__getattribute__()。
示例
>>> def traceCall(*args):#跟蹤調(diào)用 if trace: print('['+','.join(map(str,args))+']') >>> def accessCtrl(forbid): def onDecorator(aCls): class onInstance: def __init__(self,*args,**kargs): self.__wrapped=aCls(*args,**kargs) def __getattr__(self,attr): traceCall('getattr',attr) if forbid(attr): raise TypeError('禁止訪問:'+attr) else: return getattr(self.__wrapped,attr) def __setattr__(self,attr,value): traceCall('setattr',attr,value) # 壓縮后的變量名為 _onInstance__wrapped if attr=='_onInstance__wrapped': self.__dict__[attr]=value elif forbid(attr): raise TypeError('禁止設(shè)置:'+attr) else: setattr(self.__wrapped,attr,value) return onInstance return onDecorator >>> def privateAttr(*privates): return accessCtrl(forbid=(lambda attr:attr in privates)) >>> @privateAttr('phone') class Staff_Private: def __init__(self,name,phone): self.name=name self.phone=phone def __str__(self): return 'Staff_Private->手機(jī)號:'+str(self.phone) def __add__(self,num): self.phone+=num
Python2.x執(zhí)行
Py2的__getattr__()攔截print()和+等內(nèi)置操作的表達(dá)式調(diào)用,正確的委托給裝飾對象。
#python2.x執(zhí)行 >>> trace=True >>> sp1=Staff_Private('梯閱線條',110) [setattr,_onInstance__wrapped,Staff_Private->手機(jī)號:110] #py2傳統(tǒng)類 攔截內(nèi)置操作表達(dá)式調(diào)用-隱式調(diào)用,print() >>> print(sp1) [getattr,__str__] Staff_Private->手機(jī)號:110 #py2傳統(tǒng)類 攔截內(nèi)置操作表達(dá)式調(diào)用-隱式調(diào)用,+ >>> sp1+1 [getattr,__coerce__] [getattr,__add__] >>> print(sp1) [getattr,__str__] Staff_Private->手機(jī)號:111
Python3.x執(zhí)行
Py3的__getattr__()不攔截print()和+等內(nèi)置操作的表達(dá)式調(diào)用,無法委托給裝飾對象。
#python3.x執(zhí)行 >>> trace=True >>> sp1=Staff_Private('梯閱線條',110) [setattr,_onInstance__wrapped,Staff_Private->手機(jī)號:110] #py3沒有攔截內(nèi)置操作 print >>> print(sp1) <__main__.accessCtrl.<locals>.onDecorator.<locals>.onInstance object at 0x0000019736C2F4F0> #py3沒有攔截內(nèi)置操作 + >>> sp1+1 Traceback (most recent call last): File "<pyshell#11>", line 1, in <module> sp1+1 TypeError: unsupported operand type(s) for +: 'onInstance' and 'int'
1.2 裝飾器重載內(nèi)置操作
描述
Python3.x的裝飾器重載內(nèi)置操作運(yùn)算符方法,來攔截裝飾類對應(yīng)的內(nèi)置表達(dá)式調(diào)用。
比如,重載__str__()攔截print(),__add__()攔截+。
示例
>>> def traceCall(*args):#跟蹤調(diào)用 if trace: print('['+','.join(map(str,args))+']') >>> def accessCtrl(forbid): def onDecorator(aCls): class onInstance: def __init__(self,*args,**kargs): self.__wrapped=aCls(*args,**kargs) def __getattr__(self,attr): traceCall('getattr',attr) if forbid(attr): raise TypeError('禁止訪問:'+attr) else: return getattr(self.__wrapped,attr) def __setattr__(self,attr,value): traceCall('setattr',attr,value) # 壓縮后的變量名為 _onInstance__wrapped if attr=='_onInstance__wrapped': self.__dict__[attr]=value elif forbid(attr): raise TypeError('禁止設(shè)置:'+attr) else: setattr(self.__wrapped,attr,value) # print()觸發(fā)__str__() def __str__(self): traceCall('onInstance,__str__') # str()觸發(fā)__str__() return str(self.__wrapped) # + 觸發(fā) __add__() def __add__(self,other): traceCall('onInstance,__add__',other) return self.__wrapped+other return onInstance return onDecorator >>> def privateAttr(*privates): return accessCtrl(forbid=(lambda attr:attr in privates)) >>> @privateAttr('phone') class Staff_Private: def __init__(self,name,phone): self.name=name self.phone=phone def __str__(self): traceCall('Staff_Private,__str__') return 'Staff_Private->手機(jī)號:'+str(self.phone) def __add__(self,num): traceCall('Staff_Private,__add__',num) self.phone+=num >>> trace=True >>> sp1=Staff_Private('梯閱線條',110) [Staff_Private,__str__]#traceCall調(diào)用print()觸發(fā)__str__() [setattr,_onInstance__wrapped,Staff_Private->手機(jī)號:110] # print()觸發(fā)__str__() >>> print(sp1) [onInstance,__str__] [Staff_Private,__str__] Staff_Private->手機(jī)號:110 # + 觸發(fā) __add__() >>> sp1+1 [onInstance,__add__,1] [Staff_Private,__add__,1] >>> print(sp1) [onInstance,__str__] [Staff_Private,__str__] Staff_Private->手機(jī)號:111
到此這篇關(guān)于Python裝飾器重載內(nèi)置的使用的文章就介紹到這了,更多相關(guān)Python裝飾器重載內(nèi)置內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
pyqt6實(shí)現(xiàn)關(guān)閉窗口前彈出確認(rèn)框的示例代碼
本文主要介紹了pyqt6實(shí)現(xiàn)關(guān)閉窗口前彈出確認(rèn)框的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-02-02python中l(wèi)eastsq函數(shù)的使用方法
這篇文章主要介紹了python中l(wèi)eastsq函數(shù)的使用方法,leastsq作用是最小化一組方程的平方和,下面文章舉例說明詳細(xì)內(nèi)容,具有一的參考價(jià)值,需要的小伙伴可以參考一下2022-03-03Python中利用all()來優(yōu)化減少判斷的實(shí)例分析
在本篇文章里小編給大家整理的是一篇關(guān)于Python中利用all()來優(yōu)化減少判斷的實(shí)例分析內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。2021-06-06windows環(huán)境中利用celery實(shí)現(xiàn)簡單任務(wù)隊(duì)列過程解析
這篇文章主要介紹了windows環(huán)境中利用celery實(shí)現(xiàn)簡單任務(wù)隊(duì)列過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11Python?字符串使用多個(gè)分隔符分割成列表的2種方法
本文主要介紹了Python?字符串使用多個(gè)分隔符分割成列表,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04