# 为什么需要**有参装饰器**?
已经知道普通装饰器能给函数加功能,但**有参装饰器**(带参数的装饰器)是为了解决:**让装饰器的功能可以灵活配置、重复使用、适应不同场景**。
---
## 一、普通装饰器的痛点:**功能写死,不能改**
普通装饰器的逻辑是**固定死**的:
- 日志只能固定前缀
- 计时只能固定输出
- 权限只能固定等级
**无法灵活变化!**
例子:
```pythondef log_decorator(func): def wrapper(*args, **kwargs): print("日志:开始执行") # 写死了! return func(*args, **kwargs) return wrapper```
你想让:
- A函数用 `[DEBUG]` 日志
- B函数用 `[INFO]` 日志
- C函数用 `[ERROR]` 日志
**普通装饰器做不到!**
---
## 二、有参装饰器的作用:**让装饰器变成可配置的工具**
有参装饰器 = **可以传参数的装饰器**
它能让你:
```python@log(level="DEBUG")def func1(): ...@log(level="INFO")def func2(): ...@log(level="ERROR")def func3(): ...```
**同一个装饰器,不同参数 → 完全不同的行为!**
---
## 三、一句话总结:为什么需要有参装饰器?
### ✔ 让装饰器**灵活可配置**
### ✔ 让同一个装饰器**适应不同场景**
### ✔ 让代码**更通用、更少重复**
### ✔ 让功能**可动态控制**(开关、等级、模式、前缀等)
没有有参装饰器,你就必须为每一种日志、每一种权限、每一种格式写一个新装饰器,代码会爆炸。
---
## 四、最经典的使用场景(一看就懂)
1. **日志等级**:DEBUG / INFO / WARNING / ERROR
2. **权限控制**:admin / user / guest
3. **缓存时间**:缓存5秒、10秒、30秒
4. **重试次数**:失败重试1次、3次、5次
5. **超时时间**:10秒超时 / 30秒超时
6. **自定义前缀**:不同函数用不同日志前缀
这些**必须传参才能实现**。
---
## 五、最简单的有参装饰器示例
```python# 有参装饰器 = 三层函数嵌套def log(prefix): # 第一层:接收装饰器参数 def decorator(func): # 第二层:接收被装饰函数 def wrapper(*args, **kwargs): # 第三层:包装执行 print(f"[{prefix}] 函数开始运行") return func(*args, **kwargs) return wrapper return decorator# 使用:传参数!@log("DEBUG")def test(): print("我是函数")test()'''@OutPut : [DEBUG] 函数开始运行我是函数'''```
---
### 最终总结(超级好记)
- **普通装饰器**:功能固定,不能改
- **有参装饰器**:**功能可配置,灵活多变**
**有参装饰器就是为了让装饰器从“固定工具”变成“万能可调工具”!**
# 有参装饰器的本质
有参装饰器的本质是在外边再次套一个def使用时@这个新建的函数,并在这个新函数中传递参数
## 一、有参装饰器本质:三层函数嵌套
普通装饰器是 **2层**,有参装饰器是 **3层**:
```text@decorator(arg1, arg2) ← 你写的语法糖 ↓def 外层(参数): ← 第1层:接收装饰器参数 def 中层(函数): ← 第2层:接收被装饰函数(普通装饰器层) def 内层(*args, **kwargs): ← 第3层:真正执行时调用 # 前置逻辑 result = 函数(*args, **kwargs) # 后置逻辑 return result return 内层 return 中层```
## 执行顺序(非常关键)
1. 定义函数时:
`外层(参数)` → 返回中层
→ `中层(原函数)` → 返回内层
2. 调用函数时:
执行的是 **内层函数**
---
## 二、最标准通用模板(可直接复制用)
```pythondef 有参装饰器(装饰器参数): # 这里可以用 装饰器参数 def 真正的装饰器(被装饰函数): def 包装函数(*args, **kwargs): # 执行前逻辑 result = 被装饰函数(*args, **kwargs) # 执行后逻辑 return result return 包装函数 return 真正的装饰器```
---
# 三、一句话记住
- **第1层:接收装饰器的参数**
- **第2层:接收要装饰的函数**
- **第3层:接收函数调用的参数,并执行逻辑**