函式裝飾器可以是普通函式,也可以是可呼叫類(具有呼叫(方法的類,可以像帶括號的函式一樣呼叫,自動呼叫呼叫(方法,即具有call(method)的類例項,稱為可呼叫類的例項)。
函式裝飾器可以修飾普通函式或類方法。
當類方法用普通函式修飾時,python 會將隱式 body 例項傳遞給 self;
當類方法被可呼叫的類例項修飾時,Python 只傳遞該類的乙個例項,並且可以通過顯式傳遞修飾的類例項來正確呼叫類方法。
用法:
>>class counttrace:描述:正如前面描述符部分中的習,描述符是乙個具有 get (set (delete ( 方法的類,並將這樣的例項分配給另乙個類的屬性以供使用。def __init__(self,func):
self.calls=0
self.func=func
例項名()操作,自動呼叫呼叫
致電加薪(0.2)自動呼叫counttrace的呼叫
呼叫 call ( 時,第乙個輸入引數 self 是 counttrace 類的例項。
payraise(self,rate) 的 self 為 02、不自動傳遞當前呼叫的 StaffWithDecorator 類例項。
def __call__(self,*args,**kargs):
print('self=',self)
print('*args=',args)
self.calls+=1
print('呼叫 {} 次'.format(func.__name__,calls))
return func(*args,**kargs)
return wrapper
>counttrace
def testsquare(x):
print(x**2)
>class staffwithdecorator:
def __init__(self,name,pay):
self.name=name
self.pay=pay
巢狀函式修飾類方法,這些方法在呼叫時自動將類例項傳遞給 *args to self
counttrace
def payraise(self,rate):
print('self=',self)
self.pay*=(1.0+rate)
>testsquare(3)
func=
args= (3,)
呼叫 testsquare 1 次。
>s1=staffwithdecorator('張三',51000)
>s1.payraise(0.2)
func=
args= (,0.2)
致電加薪 1 次。
self= <_main__.staffwithdecorator object at>
>s1.pay
get (截獲屬性的點運算,call (截獲例項的括號運算。
當描述符同時定義 call 和 get 時,get 方法需要返回乙個可呼叫的物件,例如例項本身,否則無法對例項的括號進行算術運算。
get 方法有三個引數:self、instance 和 owner。
例
>>class getclass:描述:描述符是具有 get、set 和 delete 方法的類,將描述符類的例項分配給另乙個類的屬性將自動攔截該屬性的點、賦值和刪除操作。get(攔截點。 操作。
您需要自行返回例項本身
執行括號算術。
def __get__(self,instance,owner):
print('獲取屬性')
return self
call (截獲括號() 操作。
def __call__(self):
print('可呼叫的類例項')
>class testget:
gc=getclass()
>tg=testget()
時期。 操作。
>tg.gc
獲取屬性<_main__.getclass object at>
時期。 算術和括號 () 算術。
>tg.gc()
獲取屬性可呼叫的類例項
裝飾器作為描述符編寫,修飾後的 body 類方法反彈到描述符類例項,在執行點和括號操作時自動呼叫描述符的 get 和 call 方法。
描述符可以修飾普通函式和類方法。
1)裝飾器定義呼叫方法
2)裝飾器定義get(方法,該方法接收描述符類例項和主體類例項,返回可呼叫例項,該可呼叫例項的建構函式接收描述符類例項和主體類例項;
3)當返回的可呼叫例項進行括號操作時,執行描述符類例項的括號操作,呼叫描述符類的呼叫方法,並將主體類例項的輸入引數和主體類例項的原始類方法傳遞給*args。
例
>>class counttrace:def __init__(self,func):
self.calls=0
self.func=func
例項名()操作,自動呼叫呼叫
def __call__(self,*args,**kargs):
print('self1=',self)
print('*args=',args)
self.calls+=1
print('呼叫 {} 次'.format(self.func.__name__,self.calls))
return self.func(*args,**kargs)
def __get__(self,instance,owner):
print('self2=',self)
print('instance=',instance)
print('owner=',owner)
返回可呼叫物件,否則括號無法算術。
return wrapper(self,instance)
>class wrapper:
def __init__(self,desc,subj):
self.desc=desc
self.subj=subj
定義括號。
def __call__(self,*args,**kargs):
例項括號操作,desc() 呼叫 counttrace 的呼叫
return self.desc(self.subj,*args,**kargs)
>counttrace
def testsquare(x):
print(x**2)
>class staffwithdecorator:
def __init__(self,name,pay):
self.name=name
self.pay=pay
counttrace
def payraise(self,rate):
print('self3=',self)
self.pay*=(1.0+rate)
>testsquare(3)
self1= <_main__.counttrace object at>
args= (3,)
呼叫 testsquare 1 次。
>s1=staffwithdecorator('張三',51000)
>s1.payraise(0.2)
self2= <_main__.counttrace object at>
instance= <_main__.staffwithdecorator object at>
owner=
self1= <_main__.counttrace object at>
args= (,0.2)
致電加薪 1 次。
self3= <_main__.staffwithdecorator object at>