dnf手游360客户端
1.71 GB · 2025-11-12
装饰器本质上是一个函数,它的作用是接收一个函数或类作为输入,并返回一个被增强后的新函数或类。
换句话说:
最简单的形式如下:
def decorator(func):
def wrapper():
print("函数执行前做一些准备工作...")
func()
print("函数执行后做一些收尾工作...")
return wrapper
@decorator
def hello():
print("Hello, Python!")
hello()
输出结果:
函数执行前做一些准备工作...
Hello, Python!
函数执行后做一些收尾工作...
当我们在 hello() 前加上 @decorator,相当于执行:
hello = decorator(hello)
这就是装饰器的核心原理。
我们用上面的例子来拆解执行过程:
hello() 时,检测到 @decoratordecorator(hello),并返回内部函数 wrapperhello 被替换成 wrapperhello() 实际上执行的是 wrapper()通过这种方式,我们可以在函数执行的前后插入任意逻辑,而不必修改原函数体。
如果被装饰的函数有参数怎么办?
没问题,只需让 wrapper 支持传入参数即可。
def logger(func):
def wrapper(*args, **kwargs):
print(f"开始执行函数:{func.__name__}")
result = func(*args, **kwargs)
print(f"函数 {func.__name__} 执行结束")
return result
return wrapper
@logger
def add(a, b):
return a + b
print(add(3, 5))
输出:
开始执行函数:add
函数 add 执行结束
8
有时候我们希望给装饰器本身传递参数,比如设置日志级别、权限名称等。
这就需要再包一层函数:
def log(level):
def decorator(func):
def wrapper(*args, **kwargs):
print(f"[{level}] 开始执行 {func.__name__}")
result = func(*args, **kwargs)
print(f"[{level}] 执行结束 {func.__name__}")
return result
return wrapper
return decorator
@log("INFO")
def multiply(a, b):
return a * b
multiply(2, 4)
输出:
[INFO] 开始执行 multiply
[INFO] 执行结束 multiply
这里 @log("INFO") 实际上是执行了 log("INFO"),返回一个真正的装饰器函数。
多个装饰器可以层层嵌套,执行顺序为自下而上。
def deco1(func):
def wrapper():
print("进入 deco1")
func()
print("离开 deco1")
return wrapper
def deco2(func):
def wrapper():
print("进入 deco2")
func()
print("离开 deco2")
return wrapper
@deco1
@deco2
def hello():
print("Hello!")
hello()
执行结果:
进入 deco1
进入 deco2
Hello!
离开 deco2
离开 deco1
解释:hello = deco1(deco2(hello))
一个常见问题是:装饰后的函数 __name__ 和 __doc__ 会被替换为 wrapper 的信息。
为了解决这个问题,Python 提供了 functools.wraps:
from functools import wraps
def logger(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"执行 {func.__name__}")
return func(*args, **kwargs)
return wrapper
@logger
def greet():
"""打印问候语"""
print("Hi there!")
print(greet.__name__) # greet
print(greet.__doc__) # 打印问候语
@wraps(func) 可以保留原函数的元信息,提升代码的可读性和可维护性。
装饰器不仅可以是函数,也可以是类。
只要类实现了 __call__() 方法,它就能像函数一样被调用。
class Timer:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
import time
start = time.time()
result = self.func(*args, **kwargs)
end = time.time()
print(f"{self.func.__name__} 执行耗时:{end - start:.4f} 秒")
return result
@Timer
def slow_task():
import time
time.sleep(1)
print("任务完成")
slow_task()
输出:
任务完成
slow_task 执行耗时:1.0001 秒
这种写法适合逻辑较复杂、需要保存状态的装饰场景。
装饰器是 Python 的一项核心特性,能让代码结构更清晰、功能更模块化。 它的常见应用包括:
掌握装饰器后,你可以更优雅地编写出功能丰富且可扩展的 Python 程序。