Python 装饰器的 5 种实用场景:从日志记录到权限校验
装饰器是 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 的函数是一等公民这一设计哲学。
- 点赞
- 收藏
- 关注作者
评论(0)