裝飾器:定義乙個裝飾函式,函式必須返回乙個閉包(閉包就是執行時所需要的外部變數+函式物件,關於閉包的具體介紹,可參考函式,並且被裝飾的函式會被python自動傳遞給裝飾函式,作為裝飾函式的乙個引數。
裝飾器的具體定義:
1、把要裝飾的方法作為輸入引數;
2、在函式體內可以進行任意的操作(可以想象其中會有很多應用場景);
3、只要確保最後返回乙個可執行的函式即可(可以是原來的輸入引數函式,也可以是乙個新函式)。
裝飾器的分類
裝飾器分為無引數decorator和有引數decorator
無引數decorator:生成乙個新的裝飾器函式
有引數decorator:裝飾函式先處理引數,再生成乙個新的裝飾器函式,然後對函式進行裝飾。
使用裝飾器,需要在其他函式的上面寫個@***xx,如下面例子的@timer
舉個例子,使用裝飾器來計算執行乙個函式的耗時:
import time
def timer(func): #裝飾函式
time1=time.time()#被裝飾函式呼叫前做的事情
print("******before******")
func(*arg,**kw) #做一次函式呼叫
time2=time.time()#被裝飾函式呼叫後做的事情
print("******after******")
print("time elapsed:%s" %(time2-time1)) #計算執行被裝飾函式的耗時
@timer
def a(count): #被裝飾函式
print("執行次數:",count)
裝飾器其實就是乙個閉包,把乙個函式當做引數後返回乙個替代版函式。
裝飾函式中的閉包函式結構如下:
*** 幹一些事情
func(*arg,**kw) #執行被裝飾函式
yyy 幹另外一些事情
裝飾器的規則:
規則1:
函式func上面定義了@***x,那麼等價於 func = ***x(func)
規則2:
裝飾函式***x,必須返回乙個閉包(乙個內建函式+func)
下面來具體分析一下裝飾器整個執行過程
def deco(func):
def _deco():
print ("before myfunc() called.")
func()
print (" after myfunc() called.")
# 不需要返回func,實際上應返回原函式的返回值
return _deco
@deco #myfunc=deco(myfunc)
def myfunc():
print (" myfunc() called.")
return 'ok'
#myfunc=deco(myfunc)—>返回了乙個閉包:_deco+myfunc
myfunc() #---->執行閉包函式_deco()
myfunc() #---->執行閉包函式_deco()
執行邏輯:
deco(myfunc)
print (「before myfunc() called.」)
myfunc()
print (" after myfunc() called.")
print (" myfunc() called.")
print (" myfunc() called.")
執行過程解釋:
裝飾函式deco
被裝飾函式myfunc
@deco
def myfunc(): —>myfunc= deco(myfunc)
myfunc = deco(myfunc)幹了什麼呢?
1 呼叫了deco(myfunc)
2 返回閉包:_deco+外包變數myfunc
3 閉包賦值給了myfunc
4 提醒myfunc變為了閉包函式物件
myfunc()—>幹了什麼呢?
1 _deco()執行了
2 print (「before myfunc() called.」)
3 myfunc()
4 print (" after myfunc() called.")
myfunc()—>幹了什麼呢?
1 _deco()執行了
2 print (「before myfunc() called.」)
3 myfunc()
4 print (" after myfunc() called.")
執行結果:
被裝飾函式帶引數
def deco(func):
def _deco(*arg,**kw):
print ("before %s called." %func.__name__)
print(func(*arg,**kw))
print (" after %s called." %func.__name__)
# 不需要返回func,實際上應返回原函式的返回值
return _deco
#閉包:_deco+func
裝飾器帶引數
def deco(s):
def __deco(func):
def _deco(*arg,**kw):
print ("before %s called." %func.__name__,s)
print(func(*arg,**kw))
print (" after %s called." %func.__name__,s)
# 不需要返回func,實際上應返回原函式的返回值
return _deco
return __deco
#閉包:_deco+func
@deco("hello")
def myfunc(a,b):
print (" myfunc() called.")
return a+b
myfunc(1,2)
myfunc(3,4)
1)多了一步:deco(「hello」) —>返回了閉包:__deco+s
deco=閉包:__deco+s
2)@deco—>__deco(func)+s—>返回了乙個閉包_deco+func+s
後面的過程跟上一步的過程一樣。
內建裝飾器
python中內建的裝飾器有三個:
staticmethod:定義例項方法為靜態方法
classmethod:定義例項方法為類方法
property:對類屬性的操作
乙個函式可以同時被多個裝飾器進行裝飾,
同時對乙個函式使用多個不同的裝飾器進行裝飾時,裝飾器的順序是怎樣的呢?
@a
@b@c
def f():
pass
等價於:
f = a(b(c(f)))
python高階特性(裝飾器)
裝飾器本質上是乙個函式,該函式用來處理其他函式,它可以讓其他函式在不需要修改 的 前提下增加額外的功能,裝飾器的返回值也是乙個函式物件。它經常用於有切面需求的場景,比如 插入日誌 效能測試 事務處理 快取 許可權校驗等應用場景。首先我們先了解以下通用裝飾器的框架,幫助我們更好地理解裝飾器的用法 de...
Python高階之裝飾器
要理解python裝飾器,首先要明白在python中,函式也是一種物件,因此可以把定義函式時的函式名看作是函式物件的乙個引用。既然是引用,因此可以將函式賦值給乙個變數,也可以把函式作為乙個引數傳遞或返回。同時,函式體中也可以再定義函式。可以通過編寫乙個純函式的例子來還原裝飾器所要做的事。def de...
python語言特性之裝飾器
首先,python裝飾器的作用是 在不改變原有函式實現的前提下,給此函式增加一些額外的功能 在原有函式呼叫之前或者呼叫之後 好像給原有函式加上了乙個裝飾的殼子。通過乙個例子解釋python裝飾器 coding utf8 def w1 func def inner args,kwargs print ...