DEV Community

WDSEGA
WDSEGA

Posted on

Python高级技巧:8个让代码更优雅的装饰器和上下文管理器

Python的装饰器(Decorator)和上下文管理器(Context Manager)是两个被低估的强大特性。本文分享8个实用的高级技巧,涵盖缓存、重试、计时、权限检查、资源管理等常见场景。

1. 带过期时间的缓存装饰器

functools.lru_cache 很好用,但没有过期时间控制:

import time
import functools

def timed_cache(max_age_seconds=60):
    def decorator(func):
        cache = {}
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            key = (args, tuple(sorted(kwargs.items())))
            cached = cache.get(key)
            if cached and (time.time() - cached["time"]) < max_age_seconds:
                return cached["value"]
            result = func(*args, **kwargs)
            cache[key] = {"value": result, "time": time.time()}
            return result
        wrapper.cache_clear = lambda: cache.clear()
        return wrapper
    return decorator

@timed_cache(max_age_seconds=30)
def get_user_info(user_id):
    print(f"查询数据库: user_id={user_id}")
    return {"id": user_id, "name": "Test User"}
Enter fullscreen mode Exit fullscreen mode

2. 智能重试装饰器

网络请求、数据库操作等场景经常需要重试机制:

def retry(max_attempts=3, delay=1, backoff=2, exceptions=(Exception,)):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            current_delay = delay
            for attempt in range(1, max_attempts + 1):
                try:
                    return func(*args, **kwargs)
                except exceptions as e:
                    if attempt == max_attempts:
                        raise
                    time.sleep(current_delay)
                    current_delay *= backoff
        return wrapper
    return decorator

@retry(max_attempts=3, delay=1, backoff=2, exceptions=(ConnectionError, TimeoutError))
def fetch_api_data(url):
    import requests
    response = requests.get(url, timeout=5)
    response.raise_for_status()
    return response.json()
Enter fullscreen mode Exit fullscreen mode

3. 函数执行计时器

def timer(log_level=logging.INFO):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            start = time.perf_counter()
            try:
                result = func(*args, **kwargs)
                return result
            finally:
                elapsed = time.perf_counter() - start
                logger.log(log_level, f"{func.__name__} 执行耗时: {elapsed:.4f}")
        return wrapper
    return decorator
Enter fullscreen mode Exit fullscreen mode

4. 数据库事务上下文管理器

@contextmanager
def db_transaction(db_path):
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    try:
        yield cursor
        conn.commit()
    except Exception as e:
        conn.rollback()
        raise
    finally:
        conn.close()
Enter fullscreen mode Exit fullscreen mode

5. 临时目录上下文管理器

@contextmanager
def temp_directory():
    dir_path = tempfile.mkdtemp()
    try:
        yield dir_path
    finally:
        shutil.rmtree(dir_path, ignore_errors=True)
Enter fullscreen mode Exit fullscreen mode

6. 参数验证装饰器

def validate_types(**expected_types):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(**kwargs):
            for param_name, expected_type in expected_types.items():
                if param_name in kwargs:
                    value = kwargs[param_name]
                    if not isinstance(value, expected_type):
                        raise TypeError(f"参数类型错误: {param_name}")
            return func(**kwargs)
        return wrapper
    return decorator
Enter fullscreen mode Exit fullscreen mode

7. 异步并发限制装饰器

def async_rate_limit(max_concurrent=5):
    semaphore = asyncio.Semaphore(max_concurrent)
    def decorator(func):
        @functools.wraps(func)
        async def wrapper(*args, **kwargs):
            async with semaphore:
                return await func(*args, **kwargs)
        return wrapper
    return decorator
Enter fullscreen mode Exit fullscreen mode

8. 单例模式装饰器

def singleton(cls):
    instances = {}
    @functools.wraps(cls)
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance
Enter fullscreen mode Exit fullscreen mode

装饰器和上下文管理器的核心思想是将横切关注点从业务逻辑中分离出来。合理使用它们,可以让你的代码更简洁、更健壮、更易维护。


📢 本文为精简版,完整版包含独家工具推荐和深度分析,请访问 WD Tech Blog 查看!

关注我的博客获取最新科技资讯、AI教程和效率工具推荐!

Top comments (0)