Python 多个装饰器叠加的执行顺序
技术百科
冰川箭仙
发布时间:2026-01-20
浏览: 次 多个装饰器叠加时,装饰阶段从下往上执行,调用阶段从上往下执行。即定义时按@decorator_c、@decorator_b、@decorator_a顺序包装,等价于decorator_a(decorator_b(decorator_c(func)));调用时先执行decorator_a前置逻辑,再b、c,最后原函数,后置逻辑则逆序执行。
多个装饰器叠加时,执行顺序分两阶段:装饰阶段(定义时)从下往上,调用阶段(运行时)从上往下。
装饰阶段:从下往上包装
当函数上方写有多个装饰器时,Python 会按从下到上的顺序应用它们。也就是说,最靠近函数的装饰器最先执行,其返回结果作为下一个装饰器的输入。
例如:
@decorator_a
@decorator_b
@decorator_c
def my_func():
pass
等价于:
my_func = decorator_a(decorator_b(decorator_c(my_func)))
即:decorator_c 先包装 my_func,然后 decorator_b 包装 decorator_c 的结果,最后 decorator_a 包装 decorator_b 的结果。
调用阶段:从上往下执行
当调用 my_func() 时,由于最外层是 decorator_a 的返回函数,所以先执行 decorator_a 内部逻辑,再进入 decorator_b,最后到 decorator_c,然后才真正执行原函数。
典型执行流(假设每个装饰器都打印一行):
- decorator_a 的前置逻辑
- decorator_b 的前置逻辑
- decorator_c 的前置逻辑
- my_func 原始逻辑
- decorator_c 的后置逻辑
- decorator_b 的后置逻辑
- decorator_a 的后置逻辑
验证顺序的小技巧
写一个带 print 的简单装饰器,观察输出即可确认顺序:
def make_decorator(name):
print(f"[装饰阶段] {name} 正在包装")
def decorator(func):
print(f"[装饰阶段] {name} 已包装 {func.__name__}")
def wrapper(*args, **kwargs):
print(f"[调用阶段] 进入 {name}")
result = func(*args, **kwargs)
print(f"[调用阶段] 离开 {name}")
return result
return wrapper
return decorator
@make_decorator('A')
@make_decorator('B')
@make_decorator('C')
def hello():
print("hello world")
运行 hello() 会看到:装饰阶段按 C→B→A 输出;调用阶段按 A→B→C 进入,C→B→A 离开。
关键记忆点
- 装饰器语法 @a @b @c func 是“糖”,本质是 c(b(c(func)))
- 装饰阶段只发生一次,在函数定义完成时
- 调用阶段每次执行函数都会走完整嵌套链
- 前置逻辑(装饰器内 wrapper 中 func 前的代码)按 A→B→C 执行;后置逻辑(func 后的代码)按 C→B→A 执行
# 多个
# 小技巧
# python
# app
# 也就是说
# 往下
# class
# php
# print
# 往上
# brush
# 最外层
# 从下到上
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Bpmn 2.0的XML文件怎么画流程图
- Win11如何设置开机自动联网 Win11宽带连接
- Win11怎么查看显卡温度 Win11任务管理器查
- c++中如何使用虚函数实现多态_c++多态性实现原
- PHP的FastAdmin架构适合二次开发吗_特点
- php转exe用什么工具打包快_高效打包软件推荐【
- Windows10无法识别USB设备描述符请求失败
- Win11怎么开启游戏模式_Win11优化游戏帧数
- MAC如何设置网卡MAC地址克隆_MAC终端修改物
- Linux怎么修改用户密码_Linux系统pass
- Win11更新后变慢怎么办_Win11系统更新后卡
- Python lxml的etree和Element
- php打包exe后无法读取环境变量_变量配置方法【
- Win11如何设置计划任务 Win11定时执行程序
- c++中的可变参数模板(variadic temp
- php8.4如何配置ssl证书_php8.4htt
- 如何在 Pandas 中按元素交集合并两列字符串
- Win11系统占用空间大怎么办 Win11深度瘦身
- c++中的std::conjunction和std
- Win11怎么设置快速访问主页_Windows11
- Go 语言标准库为何不提供泛型 Contains
- C++如何使用std::transform批量处理
- Mac如何调整Dock栏大小和位置_Mac程序坞个
- Win11色盲模式怎么开_Win11屏幕颜色滤镜设
- Python数据抓取合法性_合规说明【指导】
- Mac电脑如何恢复出厂设置_Mac抹掉数据并重装系
- 如何使用Golang进行HTTP服务性能测试_测量
- Win10如何备份注册表_Win10注册表备份步骤
- Win11任务栏天气怎么关闭 Win11隐藏天气小
- PythonDocker高级项目部署教程_多容器管
- 如何使用Golang反射创建map对象_动态生成键
- php订单日志怎么按状态筛选_php筛选不同状态订
- Windows蓝屏错误0x00000023怎么修复
- Python数据挖掘核心算法实践_聚类分类与特征工
- 使用类变量定义字符串常量时如何实现类型安全的 Li
- 如何在 Go 中创建包含映射(map)的切片(sl
- Win11怎么设置默认图片查看器_Windows1
- Python文本编码与解码_跨平台解析说明【指导】
- php打包exe如何加密代码_防反编译保护方法【技
- Win11怎么清理C盘虚拟内存_Win11清理虚拟
- Mac如何备份到iCloud_Mac桌面与文稿文件
- Windows如何使用BitLocker To G
- Windows10无法连接到Internet_Wi
- Python网络日志追踪_请求定位解析【教程】
- Win11屏幕亮度突然变暗怎么解决_自动变暗问题处
- Win10如何更改网络连接_Windows10以太
- 手机php文件怎么变成mp4_安卓苹果打开php转
- Linux怎么设置磁盘配额_Linux系统Quot
- VSC怎么配置PHP的Xdebug_远程调试设置步
- Windows家庭版如何开启组策略(gpedit.


QQ客服