Python的裝飾器

2021-10-04 07:29:54 字數 3726 閱讀 2646

在python中使用裝飾器可以在不修改**的前提下為已有的函式新增新功能. 例如計算函式的執行時間, 列印函式的執行日誌, 快取資料, 使用者授權等.

為什麼需要把某個功能用裝飾器的方式實現? 換句話說, 為什麼不直接在函式中實現某個功能? 或者為什麼不單獨用乙個類(class)來實現某個功能, 然後在函式中呼叫?

以提供快取功能的裝飾器為例. 假如我們的業務**負責向資料庫讀取資料, 然後返回給使用者. 為了縮短響應時間, 我們可以把資料放在快取, 從而降低io. 站在業務的角度, 快取功能實際上與我們需要實現的業務功能無關. 為了保持業務**的簡潔, 我們可以把通用的與業務邏輯無關的功能用裝飾器來實現, 即面向切面程式設計的思想.

我們想實現乙個計時的裝飾器timer. 使用效果如下所示:

# main.py

import time

@timer

deftest()

: time.sleep(

1.0)

if __name__ ==

'__main__'

: test(

)

time cost: 1.0013980865478516
裝飾器timer的輸入引數是乙個函式物件, 返回的結果也是乙個函式物件. 返回的函式是乙個「附加了新功能的」函式. 在上面的例子中, 裝飾器@timer實際上是乙個執行如下操作的語法糖.

)完整**

import time

# 裝飾器函式

deftimer

(func)

:# 呼叫func並計時

def(

*args,

**kwargs)

: t1 = time.time(

) func(

*args,

**kwargs)

print

("time cost:"

, time.time(

)- t1)

@timer

deftest()

: time.sleep(

1.0)

if __name__ ==

'__main__'

: test(

)

裝飾後的函式名

>>

>

print

(test.__name__)

import time

from functools import wraps

# 裝飾器函式

deftimer

(func)

:# 呼叫func並計時

@wraps(func)

# 保持func的函式名

def(

*args,

**kwargs)

: t1 = time.time(

) func(

*args,

**kwargs)

print

("time cost:"

, time.time(

)- t1)

下面我們要把計時器的功能稍微擴充一下. 實現乙個帶引數的計時器@timer_unit(unit), 其中引數unit代表了計時的單位:'s' -- 秒; 'ms' -- 毫秒. 前文提到裝飾器函式的輸入必須是乙個函式物件, 否則如何接收函式物件? 注意到函式名加括號timer_unit(unit='s')代表執行乙個函式, 因此我們只需要讓函式timer_unit(unit='s')的執行結果返回乙個普通的裝飾器即可.

# 帶引數的裝飾器

deftimer_unit

(unit=

's')

:# 普通裝飾器

defdecorator

(func)

:# 呼叫func並計時

@wraps(func)

# 保持func的函式名

def(

*args,

**kwargs)

: t1 = time.time(

) func(

*args,

**kwargs)

multiplier =

1if unit ==

'ms'

: multiplier =

1000

print

("time cost (unit: %s):"

% unit,

(time.time(

)- t1)

* multiplier)

# 返回普通裝飾器

return decorator

import time

from functools import wraps

class

timer

(object):

""" 乙個用來計時的裝飾器類

需要實現__call__方法, 可以像函式一樣呼叫例項

"""def__init__

(self)

: self._multiplier =

1# 秒

self._unit =

none

# 's'-秒; 'ms'-毫秒; 'mus' - 微秒

def_get_multiplier

(self)

:if self._unit ==

'ms'

:# 毫秒

self._multiplier =

1000

if self._unit ==

'mus'

:# 微秒

self._multiplier =

1000000

return self._multiplier

def__call__

(self, unit=

's')

: self._unit = unit

defdecorator

(func)

:

@wraps(func)

def(

*args,

**kwargs)

: t1 = time.time(

) func(

*args,

**kwargs)

print

("time cost (unit: %s):"

% unit,

(time.time(

)- t1)

* self._get_multiplier())

return decorator

# 裝飾器函式

timer_class = timer(

)@timer_class(unit=

'mus'

)def

test()

: time.sleep(1)

if __name__ ==

'__main__'

: test(

)

python裝飾器 Python 裝飾器

簡言之,python裝飾器就是用於拓展原來函式功能的一種函式,這個函式的特殊之處在於它的返回值也是乙個函式,使用python裝飾器的好處就是在不用更改原函式的 前提下給函式增加新的功能。一般而言,我們要想拓展原來函式 最直接的辦法就是侵入 裡面修改,例如 這是我們最原始的的乙個函式,然後我們試圖記錄...

python裝飾器 裝飾器

由於函式也是乙個物件,而且函式物件可以被賦值給變數,所以,通過變數也能呼叫該函式。def now print 2015 3 25 f now f 2015 3 25 函式物件有乙個 name 屬性,可以拿到函式的名字 now.name now f.name now 現在,假設我們要增強now 函式的...

python裝飾器原理 Python裝飾器原理

裝飾器 decorator 是物件導向設計模式的一種,這種模式的核心思想是在不改變原來核心業務邏輯 的情況下,對函式或類物件進行額外的修飾。python中的裝飾器由python直譯器直接支援,其定義形式如下 decorator def core service 要理解上述 的含義,我們從自定義函式裝...