文章目錄
- 代碼解析
- 1. 裝飾器定義 timer(func)
- 2. 應用裝飾器 @timer
- **執行流程**
- **關鍵點**
- **實際應用場景**
- **改進版本(帶 `functools.wraps`)**
這是一個 Python 裝飾器(Decorator) 的示例,用于測量函數的執行時間。下面詳細解析它的工作原理和用法:
代碼解析
1. 裝飾器定義 timer(func)
def timer(func):def wrapper(*args, **kwargs):start = time.time() # 記錄開始時間result = func(*args, **kwargs) # 執行被裝飾的函數end = time.time() # 記錄結束時間print(f"函數 {func.__name__} 執行時間: {end-start:.2f}秒") # 打印耗時return result # 返回原函數的結果return wrapper
timer(func)
是一個裝飾器工廠函數,接收一個函數func
作為參數。wrapper(*args, **kwargs)
是實際替換原函數的包裝函數:*args
和**kwargs
確保它可以處理任意參數(位置參數和關鍵字參數)。- 在調用原函數
func(*args, **kwargs)
前后分別記錄時間,計算并打印耗時。 - 最后返回原函數的結果
result
,確保裝飾器不影響原函數的功能。
2. 應用裝飾器 @timer
@timer
def long_running_function():time.sleep(2)
@timer
是語法糖,等價于:long_running_function = timer(long_running_function)
- 調用
long_running_function()
時,實際執行的是wrapper()
函數。
執行流程
- 調用
long_running_function()
。 - 進入
wrapper(*args, **kwargs)
:- 記錄
start
時間。 - 執行原函數
func()
(即time.sleep(2)
)。 - 記錄
end
時間,計算耗時并打印。 - 返回原函數的結果(此處為
None
,因為time.sleep()
無返回值)。
- 記錄
輸出示例:
函數 long_running_function 執行時間: 2.00秒
關鍵點
-
裝飾器的作用:
- 在不修改原函數代碼的情況下,為其添加新功能(如日志、計時、權限檢查等)。
- 符合 開放-封閉原則(對擴展開放,對修改封閉)。
-
*args
和**kwargs
:- 確保裝飾器能處理任意參數的函數。例如:
調用@timer def add(a, b):return a + b
add(1, b=2)
時,args
為(1,)
,kwargs
為{'b': 2}
。
- 確保裝飾器能處理任意參數的函數。例如:
-
函數屬性保留:
- 裝飾后函數的
__name__
會變成wrapper
,可通過functools.wraps
修復:from functools import wrapsdef timer(func):@wraps(func)def wrapper(*args, **kwargs):# ...原有邏輯return wrapper
- 裝飾后函數的
實際應用場景
- 性能分析:統計函數執行時間。
- 日志記錄:記錄函數調用參數和結果。
- 權限驗證:在函數執行前檢查用戶權限。
- 緩存:緩存函數結果以避免重復計算(如
@lru_cache
)。
改進版本(帶 functools.wraps
)
import time
from functools import wrapsdef timer(func):@wraps(func) # 保留原函數的元信息(如 __name__)def wrapper(*args, **kwargs):start = time.time()result = func(*args, **kwargs)end = time.time()print(f"函數 {func.__name__} 執行時間: {end-start:.2f}秒")return resultreturn wrapper
這樣,long_running_function.__name__
仍會返回 "long_running_function"
,而不是 "wrapper"
。