带参数的装饰器怎么用?(用大白话讲清楚)
装饰器就像给函数加个“外壳”,让它在执行时额外做些事情。
但是,如果装饰器本身也需要参数,就得先告诉装饰器要怎么做,然后再装饰具体的函数。
所以,带参数的装饰器要多一层嵌套,先拿到参数,再装饰函数。
🟢 举个例子:一个可以控制日志级别的装饰器
假设你有个 log(level) 装饰器:
- 可以指定日志级别 (
INFO、WARNING、ERROR) - 在执行函数前后打印日志
- 让不同的函数可以选择不同的日志级别
📝 代码示例
import time
# 这是一个带参数的装饰器
def log(level="INFO"): # ❶ 先接受参数
def decorator(func): # ❷ 这个才是真正的装饰器
def wrapper(*args, **kwargs): # ❸ 这个是包装函数
print(f"[{level}] 开始执行 {func.__name__} ...") # ❹ 记录日志
start = time.perf_counter()
result = func(*args, **kwargs) # ❺ 执行原函数
end = time.perf_counter()
print(f"[{level}] {func.__name__} 执行完成,耗时 {end - start:.4f} 秒") # ❻ 记录耗时
return result # ❼ 返回原函数的结果
return wrapper # ❽ 返回包装后的函数
return decorator # ❾ 返回装饰器
✅ 使用方法
1️⃣ 使用默认 INFO 级别
@log() # 相当于 @log("INFO")
def add(a, b):
time.sleep(1) # 模拟计算
return a + b
print(add(3, 5))
输出:
[INFO] 开始执行 add ...
[INFO] add 执行完成,耗时 1.0003 秒
8
✅ 这里 @log() 直接调用,默认是 INFO 级别。
2️⃣ 自定义 WARNING 级别
@log("WARNING") # 传入参数,指定日志级别
def multiply(a, b):
time.sleep(2)
return a * b
print(multiply(4, 6))
输出:
[WARNING] 开始执行 multiply ...
[WARNING] multiply 执行完成,耗时 2.0005 秒
24
✅ 这里 @log("WARNING") 让日志显示 WARNING 级别。
🔍 解析代码执行过程
当 @log("WARNING") 装饰 multiply(a, b) 时,Python 发生了以下事情:
- 先执行
log("WARNING"),返回decorator @decorator作用在multiply上,返回wrapper- 当
multiply(4, 6)被调用时:wrapper先打印日志- 调用原函数
multiply(a, b) - 计算耗时
- 继续打印日志
✅ 这就是为什么带参数的装饰器要多一层,因为它需要先接收参数,再装饰具体的函数。
📌 总结
-
普通装饰器:
def decorator(func): def wrapper(*args, **kwargs): print("执行前") result = func(*args, **kwargs) print("执行后") return result return wrapper直接
@decorator用,不需要额外传参。 -
带参数的装饰器:
def decorator_with_args(arg): def decorator(func): def wrapper(*args, **kwargs): print(f"参数: {arg}") return func(*args, **kwargs) return wrapper return decorator必须
@decorator_with_args(value)先传参数,才能装饰函数。
📢 最通俗的比喻:
普通装饰器像直接穿衣服,
带参数的装饰器像先挑一件衣服(选参数),然后再穿上(装饰函数)。
装饰器带参数&spm=1001.2101.3001.5002&articleId=145683124&d=1&t=3&u=ef424c134f1548758b18b3d3924815f8)
271

被折叠的 条评论
为什么被折叠?



