@即装饰器
Python裝飾器是一個很有用的功能,在很多場合都有使用,決定花點時間好好研究,現歸納總結如下:
先看看一些實例, 然后再來分析下原理 假設我們有如下的基本函數
defdo_something():
for i in range(1000000):
pass
print ("play game")
do_something()
結果如下:
play game
需求: 統計函數的執行時間
1. 不是裝飾器的裝飾器
這種實現看上去還可以,但是每次調用的是decorator,還要把函數作為一個參數傳入,使用起來就不方便了。
2. 最簡單的裝飾器
裝飾器是在函數定義時前面加@,然后跟裝飾器的實現函數。可以看出,現在只要直接調用do_something就可以了。調用的地方不要作任何修改。
3. 目標函數帶固定參數的裝飾器
?
實現很簡單, 就是給wrapper函數參加相同的參數
4. 目標函數帶不固定參數的裝飾器
?
需求2: 目標函數每次調用重復執行指定的次數
5. 讓裝飾器帶參數
6. 原理
看了這么多實例, 裝飾器的基本類型也基本上都有了。是不是清楚了呢??如果還是不清楚,那就繼續看下面的內容。
6.1 不帶參數的裝飾器
@a_decorator
deff(...):
...
#經過a_decorator后, 函數f就相當于以f為參數調用a_decorator返回結果。
f = a_decorator(f)
來分析這個式子, 可以看出至少要滿足以下幾個條件?1. 裝飾器函數運行在函數定義的時候?2. 裝飾器需要返回一個可執行的對象?3. 裝飾器返回的可執行對象要兼容函數f的參數
6.2 驗證分析
6.2.1 裝飾器運行時間
可以看出, 這里的do_something并沒有調用, 但是卻打印了decorator, 可wrapper沒有打印出來。也就是說decorator是在do_something調用的時候執行的。
?
6.2.2 返回可執行的對象
6.2.3 兼容函數f的
6.2.3 兼容函數f的參數
看到這里, 至少對不帶參數的裝飾器應該全弄清楚了, 也就是說能到看山還是山了。
6.3 帶參數的裝飾器
這里就給一個式子, 剩下的問題可以自己去想
@decomaker(argA, argB, ...)
deffunc(arg1, arg2, ...):
pass
#這個式子相當于
func = decomaker(argA, argB, ...)(func)
?
6.4 被裝飾過的函數的函數名
可以看出, do_something的函數名變成了wrapper,這不是我們想要的。原因估計各位也都清楚了。那要怎么去解決呢?
但是這個看起來是不是很不專業, python的functools.wraps提供了解決方法
到此為止, 你是不是覺得已經完全明白了呢??但事實是, 這其實還不夠
7. 裝飾器類
需求3: 讓函數只能運行指定的次數.
前面我們講的都是函數式的裝飾器, 那么類能不能成為裝飾器呢?
結果如下:
play game
play game 1
play game
play game 1
play game
play game 1
play game
play game 1
play game
play game 1
play game
play game 1
play game
play game 1
play game
play game 1
play game
play game 1
do_something run more than 10 times
play game 1
play game 1
play game 1
play game 1
play game 1
do_something1 run more than 15 times
是不是感覺有點怪, 但它確實是可行的。?在Python中, 其實函數也是對象。 反過來, 對象其實也可以像函數一樣調用, 只要在類的方法中實現__call__方法。回想一下創建對象的過程
這其實和函數調用沒
帶參數的裝飾器?fun = A.__init__(args)(fun)?不帶參數的裝飾器?fun = A.__init__(fun)()
轉載自:http://baijiahao.baidu.com/s?id=1599946084778367809&wfr=spider&for=pc
總結
- 上一篇: Python进阶之路:namedtupl
- 下一篇: 多于2个字符串的拼接,禁止使用“+”,而