使用裝飾器包裝函數,透過 time.time() 記錄呼叫前後時間差,即可非侵入式地測量任意函數執行耗時,適合效能分析與瓶頸定位。
import time
def print_timing(func):
"""裝飾器:印出函數執行時間(毫秒)"""
def wrapper(*args, **kwargs):
t1 = time.time()
result = func(*args, **kwargs)
t2 = time.time()
print(f'{func.__name__} took {(t2 - t1) * 1000:.3f} ms')
return result
return wrapper
# 使用範例:質數篩選
@print_timing
def get_prime_list(n):
"""埃拉托斯特尼篩法回傳 2 到 n 的質數列表"""
if n < 2: return []
if n == 2: return [2]
# 僅處理奇數
s = list(range(3, n + 1, 2))
mroot = n ** 0.5
half = len(s)
i = 0
m = 3
while m <= mroot:
if s[i]:
j = (m * m - 3) // 2
s[j] = 0
while j < half:
s[j] = 0
j += m
i += 1
m = 2 * i + 3
return [2] + [x for x in s if x]
if __name__ == '__main__':
print("Prime numbers from 2 to <10,000,000 using sieve algorithm")
primes = get_prime_list(10_000_000)
time.sleep(2.5) # 模擬其他工作
Prime numbers from 2 to <10,000,000 using sieve algorithm
get_prime_list took 4750.000 ms
| 技術 | 說明 |
|---|---|
裝飾器語法 @decorator | 等同 func = decorator(func),在函數定義時即完成包裝 |
*args, **kwargs | 支援任意位置/關鍵字參數透傳 |
time.time() | 回傳浮點秒數(自紀元),精度通常達微秒級 |
func.__name__ | 取得原函數名稱,輸出更易讀 |
| 保留回傳值 | return result 確保裝飾不改變原函數行為 |
time.perf_counter():更高精度、單調遞增,適合效能測量(Python 3.3+)。async def wrapper + await func(...)。logging 模組。@functools.wraps(func) 保留 __doc__、__annotations__ 等。import time
import functools
def timer(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
elapsed = (time.perf_counter() - start) * 1000
print(f'[TIMER] {func.__qualname__}: {elapsed:.3f} ms')
return result
return wrapper