W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
你想在函數(shù)上添加一個(gè)包裝器,增加額外的操作處理(比如日志、計(jì)時(shí)等)。
如果你想使用額外的代碼包裝一個(gè)函數(shù),可以定義一個(gè)裝飾器函數(shù),例如:
import time
from functools import wraps
def timethis(func):
'''
Decorator that reports the execution time.
'''
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(func.__name__, end-start)
return result
return wrapper
下面是使用裝飾器的例子:
>>> @timethis
... def countdown(n):
... '''
... Counts down
... '''
... while n > 0:
... n -= 1
...
>>> countdown(100000)
countdown 0.008917808532714844
>>> countdown(10000000)
countdown 0.87188299392912
>>>
一個(gè)裝飾器就是一個(gè)函數(shù),它接受一個(gè)函數(shù)作為參數(shù)并返回一個(gè)新的函數(shù)。當(dāng)你像下面這樣寫:
@timethis
def countdown(n):
pass
跟像下面這樣寫其實(shí)效果是一樣的:
def countdown(n):
pass
countdown = timethis(countdown)
順便說一下,內(nèi)置的裝飾器比如 @staticmethod, @classmethod,@property
原理也是一樣的。例如,下面這兩個(gè)代碼片段是等價(jià)的:
class A:
@classmethod
def method(cls):
pass
class B:
# Equivalent definition of a class method
def method(cls):
pass
method = classmethod(method)
在上面的 wrapper()
函數(shù)中,裝飾器內(nèi)部定義了一個(gè)使用 *args
和 **kwargs
來接受任意參數(shù)的函數(shù)。在這個(gè)函數(shù)里面調(diào)用了原始函數(shù)并將其結(jié)果返回,不過你還可以添加其他額外的代碼(比如計(jì)時(shí))。然后這個(gè)新的函數(shù)包裝器被作為結(jié)果返回來代替原始函數(shù)。
需要強(qiáng)調(diào)的是裝飾器并不會(huì)修改原始函數(shù)的參數(shù)簽名以及返回值。使用 *args
和 **kwargs
目的就是確保任何參數(shù)都能適用。而返回結(jié)果值基本都是調(diào)用原始函數(shù) func(*args, **kwargs)
的返回結(jié)果,其中func就是原始函數(shù)。
剛開始學(xué)習(xí)裝飾器的時(shí)候,會(huì)使用一些簡單的例子來說明,比如上面演示的這個(gè)。不過實(shí)際場景使用時(shí),還是有一些細(xì)節(jié)問題要注意的。比如上面使用 @wraps(func)
注解是很重要的,它能保留原始函數(shù)的元數(shù)據(jù)(下一小節(jié)會(huì)講到),新手經(jīng)常會(huì)忽略這個(gè)細(xì)節(jié)。接下來的幾個(gè)小節(jié)我們會(huì)更加深入的講解裝飾器函數(shù)的細(xì)節(jié)問題,如果你想構(gòu)造你自己的裝飾器函數(shù),需要認(rèn)真看一下。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: