Python 装饰器的 5 种实用场景:从日志记录到权限校验

举报
yd_297127574 发表于 2026/10/23 22:06:06 2026/10/23
【摘要】 装饰器是 Python 中最优雅的特性之一,它允许在不修改原函数代码的前提下,为函数动态添加额外功能。这种“包装”思想在真实项目中有着广泛的应用。下面通过 5 个典型场景,展示装饰器如何让代码更简洁、更健壮。**场景一:日志记录**调试和监控离不开日志。使用装饰器可以统一为关键函数加上入参和返回值记录,避免在每个函数里重复写 `print` 或 `logging`。```pythonimpo...


装饰器是 Python 中最优雅的特性之一,它允许在不修改原函数代码的前提下,为函数动态添加额外功能。这种“包装”思想在真实项目中有着广泛的应用。下面通过 5 个典型场景,展示装饰器如何让代码更简洁、更健壮。

**场景一:日志记录**

调试和监控离不开日志。使用装饰器可以统一为关键函数加上入参和返回值记录,避免在每个函数里重复写 `print` 或 `logging`。

```python
import functools, logging

def log_calls(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        logging.info(f"调用 {func.__name__},参数: {args}, {kwargs}")
        result = func(*args, **kwargs)
        logging.info(f"{func.__name__} 返回: {result}")
        return result
    return wrapper

@log_calls
def add(a, b):
    return a + b
```

`functools.wraps` 能保留原函数的元信息(名称、文档字符串),这是编写装饰器的良好习惯。

**场景二:性能计时**

定位性能瓶颈时,一个计时装饰器可以快速测量函数耗时。

```python
import time

def timer(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        print(f"{func.__name__} 耗时 {time.perf_counter() - start:.4f}s")
        return result
    return wrapper
```

只需在可疑函数上加一行 `@timer`,就能获得精确的耗时数据。

**场景三:权限校验**

在 Web 开发中,接口往往需要登录或角色校验。装饰器可以把校验逻辑从业务代码中剥离出来。

```python
def require_role(role):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(user, *args, **kwargs):
            if user.get("role") != role:
                raise PermissionError(f"需要 {role} 权限")
            return func(user, *args, **kwargs)
        return wrapper
    return decorator

@require_role("admin")
def delete_user(user, uid):
    ...
```

带参数的装饰器(三层嵌套)让权限控制更加灵活,业务函数只需关注自身逻辑。

**场景四:缓存结果**

对于计算密集或频繁调用的纯函数,缓存能显著提升性能。标准库的 `functools.lru_cache` 就是现成的装饰器,也可以手写一个简易版本。

```python
def memoize(func):
    cache = {}
    @functools.wraps(func)
    def wrapper(*args):
        if args not in cache:
            cache[args] = func(*args)
        return cache[args]
    return wrapper

@memoize
def fib(n):
    return n if n < 2 else fib(n-1) + fib(n-2)
```

注意:缓存装饰器要求参数可哈希,且适用于无副作用的函数。

**场景五:失败重试**

网络请求、数据库连接等操作容易因瞬时故障失败。重试装饰器可以自动处理这类问题。

```python
def retry(times=3, delay=1):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            for i in range(times):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if i == times - 1:
                        raise
                    time.sleep(delay)
        return wrapper
    return decorator
```

配合指数退避策略,可以进一步提升稳定性。

**总结**

日志、计时、权限、缓存、重试——这 5 个场景覆盖了从开发调试到生产运维的常见需求。装饰器的价值在于**关注点分离**:业务函数保持纯粹,横切逻辑集中管理。掌握装饰器,不仅能写出更 DRY 的代码,也能更深刻地理解 Python 的函数是一等公民这一设计哲学。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。