Python 在函式上新增包裝器

2022-09-27 14:30:12 字數 1769 閱讀 4456

問題

你想在函式上新增乙個包裝器,增加額外的操作處理(比如日誌、計時等)。

解決方案

如果你想使用額外的**包裝乙個函式,可以定義乙個裝飾器函式,例如:

import time

from functools import wrnrihpaps

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

下面是使用裝飾器的例子:

>>> www.cppcns.com@timethis

... def countdown(n):

... '''

... counts down

... '''

... while n > 0:

... n -= 1

...>>> countdown(100000)

countdown 0.008917808532714844

>>> countdown(10000000)

countdown 0.87188299392912

>>>

討論乙個裝飾器就是乙個函式,它接受乙個函式作為引數並返回乙個新的函式。當你像下面這樣寫:

@timethis

def countdown(n):

pass

跟像下面這樣寫其實效果是一樣的:

def countdown(n):

pass

countdown = timethis(countdown)

順便說程式設計客棧一下,內建的裝飾器比如 @staticmethod, @classmethod,@property 原理也是一樣的。例如,下面這兩個**片段是等價的:

class a:

@classmethod

def method(cls):

pass

class b:

# equiva程式設計客棧t definition of a class method

def method(cls):

pass

method = classmethod(method)

在上面的 wrapper() 函式中,裝飾器內部定義了乙個使用 *args 和 **kwargs 來接受任意引數的函式。在這個函式裡面呼叫了原始函式並將其結果返回,不過你還可以新增其他額外的**(比如計時)。然後這個新的函式包裝器被作為結果返回來代替原始函式。

需要強調的是裝飾器並不會修改原始函式的引數簽名以及返回值。使用 *args 和 **kwargs 目的就是確保任何引數都能適用。而返回結果值基本都是呼叫原始函式 func(*args, **kwargs) 的返回結果,其中func就是原始函式。

剛開始學習裝飾器的時候,會使用一些簡單的例子來說明,比如上面演示的這個。不過實際場景使用時,還是有一些細節問題要注意的。比如上面使用 @wraps(func) 註解是很重要的,它能保留原始函式的元資料(下一小節會講到),新手經常會忽略這個細節。接下來的幾個小節我們會更加深入的講解裝飾器函式的細節問題,如果你想構造你自己的裝飾器函式,需要認真看一下。

Python函式閉包裝飾器

x 2222 print x def func1 x 65842 deffunc2 x 65412 print x func2 func1 print x 2222 65412 2222 global 呼叫全域性變數 x 8888 deffunc1 deffunc2 global x x 10000...

python筆記 009 函式(上)

迭代是python最強大的功能之一,是訪問集合元素的一種方式 迭代器是乙個可以記住遍歷的位置的物件 迭代器物件從集合的第乙個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會後退 迭代器有兩個基本的方法 iter 和 next 字串,列表或元組物件都可用於建立迭代器 numbers 1,2...

Python 迴圈和函式(上)

1 真正的用途是用於可迭代物件 1 列表 a 1,2,3,4,5,1,2,3 aduh 2 元組 a 1,2,3,1,2,3 aduh 3 字典 a 4 集合 a 2 計數功能 range從0開始步長預設1 for i in range 10 print i range產生不變的數值串行 1 ran...