Pythonのデコレータは、関数やクラスの挙動を変更・拡張するための強力な機能です。元のコードを変更せずに、共通の処理(例:計測、ログ出力、キャッシュなど)を横断的に適用できます。以下に、実務や学習で役立つ代表的なデコレータを紹介します。
1. 実行時間計測デコレータ
import time
def measure_time(func):
def inner(*args, **kwargs):
t0 = time.perf_counter()
res = func(*args, **kwargs)
elapsed = time.perf_counter() - t0
print(f"{func.__name__} took {elapsed:.4f} seconds")
return res
return inner
@measure_time
def sample_task():
time.sleep(0.5)
sample_task()
2. 関数呼び出しログ記録デコレータ
import logging
logging.basicConfig(level=logging.DEBUG)
def log_calls(func):
def inner(*args, **kwargs):
logging.debug(f"→ {func.__name__}{args}")
result = func(*args, **kwargs)
logging.debug(f"← {func.__name__} → {result}")
return result
return inner
@log_calls
def compute(x, y):
return x * y
compute(4, 7)
3. 結果キャッシュデコレータ(LRU)
from functools import lru_cache
@lru_cache(maxsize=128)
def factorial(n):
if n <= 1:
return 1
return n * factorial(n - 1)
print(factorial(10)) # 初回計算後、再呼び出し時はキャッシュ利用
4. 引数型チェックデコレータ
def enforce_types(*types):
def decorator(func):
def wrapper(*args, **kwargs):
for val, expected in zip(args, types):
if not isinstance(val, expected):
raise TypeError(f"Expected {expected}, got {type(val)}")
return func(*args, **kwargs)
return wrapper
return decorator
@enforce_types(int, str)
def repeat(count, text):
return text * count
print(repeat(3, "hi"))
5. シングルトンパターン実装デコレータ
def singleton(cls):
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class DatabaseConnection:
def __init__(self):
self.connected = True
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2) # True
6. 例外発生時にリトライするデコレータ
import time
import random
def retry(max_attempts=3, delay=0.5):
def decorator(func):
def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts - 1:
raise
time.sleep(delay)
return None
return wrapper
return decorator
@retry(max_attempts=2)
def unstable_api():
if random.choice([True, False]):
raise ConnectionError("Network glitch")
return "OK"
print(unstable_api())
7. 関数のパフォーマンスプロファイリングデコレータ
import cProfile
import pstats
def profile_func(func):
def wrapper(*args, **kwargs):
profiler = cProfile.Profile()
profiler.enable()
result = func(*args, **kwargs)
profiler.disable()
stats = pstats.Stats(profiler)
stats.sort_stats('cumulative').print_stats(5)
return result
return wrapper
@profile_func
def heavy_computation(n):
return sum(i * i for i in range(n))
heavy_computation(100000)
8. 認証チェックデコレータ
def require_auth(authenticated=True):
def decorator(func):
def wrapper(*args, **kwargs):
if not authenticated:
raise PermissionError("Authentication required")
return func(*args, **kwargs)
return wrapper
return decorator
# 仮の認証状態
current_user_authenticated = True
@require_auth(authenticated=current_user_authenticated)
def view_dashboard():
return "Dashboard loaded"
print(view_dashboard())
9. 非同期処理ラッパーデコレータ
import asyncio
def async_wrapper(func):
async def inner(*args, **kwargs):
print("Async task started")
result = await func(*args, **kwargs)
print("Async task completed")
return result
return inner
@async_wrapper
async def fetch_data():
await asyncio.sleep(1)
return {"status": "success"}
asyncio.run(fetch_data())
10. 入力値バリデーションデコレータ
def validate_range(min_val=0, max_val=100):
def decorator(func):
def wrapper(value):
if not min_val <= value <= max_val:
raise ValueError(f"Value must be between {min_val} and {max_val}")
return func(value)
return wrapper
return decorator
@validate_range(10, 50)
def set_brightness(level):
print(f"Brightness set to {level}")
set_brightness(30)