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