Python装饰器本质是用新函数替换原函数对象,定义时立即执行赋值操作;需用functools.wraps显式继承元信息,多层装饰器按@顺序嵌套替换。
Python 装饰器的本质,就是用一个新函数替换原函数对象,同时保留原函数的名称、文档字符串等元信息(需显式处理)。它不是语法糖的幻觉,而是一次明确的赋值操作:把被装饰函数传给装饰器,再用返回值覆盖原函数名所指向的对象。
装饰器在函数定义后立即执行,不是调用时才生效。@decorator 写在 def 上方,等价于 func = decorator(func) —— 这行赋值在模块加载时就完成了。
例如:
def my_decorator(f):
print("装饰器运行了")
def wrapper(*args, **kwargs):
return f(*args, **kwargs) + 1
return wrapper
@my_decorator
def add(x):
return x + 1
运行这段代码,会立刻打印“装饰器运行了”,说明替换动作发生在 add 函数创建完成的那一刻,而非调用 add() 时。
Python 中函数是对象,变量名只是引用。装饰器改变的是引用目标,原函数体仍存在内存中(只要还有其他引用),但通过原名已无法直接访问。
直接替换后,wrapper.__name__ 是 "wrapper",不是 "add";wrapper.__doc__ 为空,不继承原函数的文档字符串。这是初学者常踩的坑。
解决方式有两种:
wrapper.__name__ = f.__name__、wrapper.__doc__ = f.__doc__

from functools import wrapsdef my_decorator(f): @wraps(f) # 关键:让 wrapper 继承 f 的 name、doc 等 def wrapper(*args, *kwargs): return f(args, **kwargs) + 1 return wrapper
@dec1
@dec2
def f(): ...
等价于 f = dec1(dec2(f)),即先用 dec2 替换 f,再用 dec1 替换 dec2(f) 的返回值。最外层装饰器最先执行,但包裹逻辑是最里层函数最先运行。