Python裝飾器重載內(nèi)置的使用
python2.x的新式類和python3.x的全部類,內(nèi)置操作表達式調(diào)用,不會觸發(fā)__getattr__()和__getattribute__()。參考《python的getattr和getattribute攔截內(nèi)置操作》。
| NO | 內(nèi)置操作表達式(隱式調(diào)用) | 對應方法(顯式調(diào)用) |
|---|---|---|
| 1 | 索引操作[i] | __getitem__ |
| 2 | 加法(連接)操作+ | __coerce__ __add__ |
| 3 | 括號調(diào)用() | __call__ |
| 4 | 打印print() | __str__ |
__coerce__:表示強制類型轉換,使用加法(或連接)操作+時,不同類型會觸發(fā)類型轉換或者報錯。
內(nèi)置操作調(diào)用方式:隱式調(diào)用,即調(diào)用表達式;顯式調(diào)用,即調(diào)用方法名。
1.1 Py3內(nèi)置操作表達式調(diào)用無法委托
描述
內(nèi)置操作的表達式調(diào)用,無法在python3.0下委托,因為不會觸發(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('禁止設置:'+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->手機號:'+str(self.phone)
def __add__(self,num):
self.phone+=num
Python2.x執(zhí)行
Py2的__getattr__()攔截print()和+等內(nèi)置操作的表達式調(diào)用,正確的委托給裝飾對象。
#python2.x執(zhí)行
>>> trace=True
>>> sp1=Staff_Private('梯閱線條',110)
[setattr,_onInstance__wrapped,Staff_Private->手機號:110]
#py2傳統(tǒng)類 攔截內(nèi)置操作表達式調(diào)用-隱式調(diào)用,print()
>>> print(sp1)
[getattr,__str__]
Staff_Private->手機號:110
#py2傳統(tǒng)類 攔截內(nèi)置操作表達式調(diào)用-隱式調(diào)用,+
>>> sp1+1
[getattr,__coerce__]
[getattr,__add__]
>>> print(sp1)
[getattr,__str__]
Staff_Private->手機號:111
Python3.x執(zhí)行
Py3的__getattr__()不攔截print()和+等內(nèi)置操作的表達式調(diào)用,無法委托給裝飾對象。
#python3.x執(zhí)行
>>> trace=True
>>> sp1=Staff_Private('梯閱線條',110)
[setattr,_onInstance__wrapped,Staff_Private->手機號: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)置操作運算符方法,來攔截裝飾類對應的內(nèi)置表達式調(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('禁止設置:'+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->手機號:'+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->手機號:110]
# print()觸發(fā)__str__()
>>> print(sp1)
[onInstance,__str__]
[Staff_Private,__str__]
Staff_Private->手機號:110
# + 觸發(fā) __add__()
>>> sp1+1
[onInstance,__add__,1]
[Staff_Private,__add__,1]
>>> print(sp1)
[onInstance,__str__]
[Staff_Private,__str__]
Staff_Private->手機號:111到此這篇關于Python裝飾器重載內(nèi)置的使用的文章就介紹到這了,更多相關Python裝飾器重載內(nèi)置內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
python中l(wèi)eastsq函數(shù)的使用方法
這篇文章主要介紹了python中l(wèi)eastsq函數(shù)的使用方法,leastsq作用是最小化一組方程的平方和,下面文章舉例說明詳細內(nèi)容,具有一的參考價值,需要的小伙伴可以參考一下2022-03-03
Python中利用all()來優(yōu)化減少判斷的實例分析
在本篇文章里小編給大家整理的是一篇關于Python中利用all()來優(yōu)化減少判斷的實例分析內(nèi)容,有需要的朋友們可以學習下。2021-06-06
windows環(huán)境中利用celery實現(xiàn)簡單任務隊列過程解析
這篇文章主要介紹了windows環(huán)境中利用celery實現(xiàn)簡單任務隊列過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-11-11

