修飾器是一個很著名的時機模式,經常用於有切面需求的場景,如插入日志、性能測試、事務處理等。修飾器能夠很好地解決這些問題,有了修飾器我們能抽離出大量函數中與函數功能本身無關的雷同代碼並繼續使用。也就是說,修飾器的作用就是為已經存在的函數對象添加額外的功能。
1.修飾器入門:
1.1.需求的由來:
修飾器的定義很抽象,先來看一個例子:
1 2 3 4def
foo():
print
"in foo()"
foo()
這個函數的功能是打印出一竄字符竄。如果想要測試執行這個函數用了多長時間,我們可以這樣做:
1 2 3 4 5 6 7 8import
time
def
foo():
start
=
time.clock()
print
"in foo()"
end
=
time.clock()
print
"used:"
,end
-
start
foo()
這樣能夠很好的達到目的。但是想測試一個模塊的所有函數的執行時間呢,就得把所有函數中都加入如上時間差的計算方法,這樣不太現實。
1.2.以不變應萬變
為了不改變原來的函數,我們可以定義一個函數timeit,將foo()的引用傳遞給他,然後在timeit中調用fool並進行計時,這樣我們就不用修改foo函數而達到目的了。
1 2 3 4 5 6 7 8 9 10 11 12import
time
def
foo():
print
"in foo()"
def
timeit(func):
start
=
time.clock()
func()
end
=
time.clock()
print
"used:"
,end
-
start
timeit(foo)
這樣看上去邏輯沒有問題,而且可以正常的工作。但卻修改了調用部分的代碼,原本是foo()調用,現在卻成了timeit(foo),如果foo在很多處都被調用了,就需要在很多處修改代碼。
1.3最大限度的少改動
如果不改動調用的代碼,也就意味著調用foo()需要產生timeit(foo)的效果。我們可以這樣做,把timeit(foo)的返回值付給foo,然後直接調用foo(),就不用修改源代碼了。
import
time
def
foo():
print
"in foo()"
def
timeit(func):
def
wrapper():
start
=
time.clock()
func()
end
=
time.clock()
print
"used:"
,end
-
start
return
wrapper
foo
=
timeit(foo)
foo()
這樣,我們只需在定義foo以後和調用foo之前,加上foo=timeit(foo),就可以達到目的了。這就是修飾器,看起來像foo被timeit修飾了。
2.正規的��飾器
上面的代碼,看似沒法再精簡了,python於是提供了一個特殊的語法來降低字符輸入量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16import
time
def
timeit(func):
def
wrapper():
start
=
time.clock()
func()
end
=
time.clock()
print
"used:"
,end
-
start
return
wrapper
@timeit
def
foo():
print
"in foo()"
foo()
在第12行的@timeit,效果和foo=timeit(foo)一樣,而且看上去更有修飾器的感覺。
這就是Python中修飾器的原理
CentOS上源碼安裝Python3.4 http://www.linuxidc.com/Linux/2015-01/111870.htm
《Python核心編程 第二版》.(Wesley J. Chun ).[高清PDF中文版] http://www.linuxidc.com/Linux/2013-06/85425.htm
《Python開發技術詳解》.( 周偉,宗傑).[高清PDF掃描版+隨書視頻+代碼] http://www.linuxidc.com/Linux/2013-11/92693.htm
Python腳本獲取Linux系統信息 http://www.linuxidc.com/Linux/2013-08/88531.htm
在Ubuntu下用Python搭建桌面算法交易研究環境 http://www.linuxidc.com/Linux/2013-11/92534.htm
Python 語言的發展簡史 http://www.linuxidc.com/Linux/2014-09/107206.htm
Python 的詳細介紹:請點這裡
Python 的下載地址:請點這裡