通用函数装饰器需用args/*kwargs适配任意参数,用functools.wraps保留元信息;支持配置时采用三层嵌套结构;异常不擅自吞掉,异步函数需单独处理。

通用函数装饰器的核心是让一个装饰器能适配任意参数的函数,关键在于用 *args 和 **kwargs 接收所有输入,并确保被装饰函数的返回值、异常行为和元信息(如函数名、文档字符串)不被破坏。
基础结构:支持任意函数签名
最简通用装饰器需包裹原函数,转发所有位置与关键字参数,并返回其结果:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("装饰器前置逻辑")
result = func(*args, **kwargs)
print("装饰器后置逻辑")
return result
return wrapper这样无论目标函数是 def f()、def g(x, y=1) 还是 def h(*a, **kw),都能正常工作。
保留原函数元信息
默认情况下,wrapper 会覆盖原函数的 __name__、__doc__ 等属性,影响调试和工具识别。应使用 functools.wraps 修复:
from functools import wraps
<p>def my_decorator(func):
@wraps(func) # 关键:复制元信息
def wrapper(*args, *<em>kwargs):
print("执行前")
result = func(</em>args, **kwargs)
print("执行后")
return result
return wrapper</p>加了 @wraps(func) 后,wrapper.__name__ 就等于原函数名,wrapper.__doc__ 也保持不变。
支持带参数的装饰器(可配置版)
若想让装饰器接收配置(如重试次数、日志级别),需再包一层函数:
def retry(max_attempts=3, delay=1):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for i in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
if i == max_attempts - 1:
raise e
time.sleep(delay)
return wrapper
return decorator
<h1>使用</h1><p>@retry(max_attempts=5, delay=0.5)
def unstable_api_call():
...
</p>这种三层嵌套结构(retry → decorator → wrapper)是实现“装饰器工厂”的标准写法。
处理异常与返回值的常见模式
通用装饰器常需统一处理错误或包装返回值。注意两点:
- 不要吞掉原函数的异常,除非明确要拦截并转换
- 若修改返回值(如加日志字段、转 JSON),确保调用方兼容——尤其是返回
None的函数不宜擅自改为字典 - 异步函数需单独处理:普通装饰器不适用于
async def,要用async def wrapper并用await func(...)











