Python装饰器与包装函数执行顺序解析:代码运行序列困惑
Python装饰器与包装函数执行顺序解析
先看你写的测试代码:
def DecoratorFun(func): # first wrapper function defined in a decorator is returned print("DecoratorFun is called") def WrapperFun1(): print("In DecoratorFun and WrapperFun1") func() print("after WrapperFun1") return WrapperFun1 # WrapperFun2 is not called or returned (ignored and lost ?) def WrapperFun2(): print("In DecoratorFun and WrapperFun2") func() print("after WrapperFun2") return WrapperFun2 @DecoratorFun def TestFun(): print("In Test Function") print("\n") print(DecoratorFun(TestFun)())
运行输出:
DecoratorFun is called In DecoratorFun and WrapperFun1 In DecoratorFun and WrapperFun1 In Test Function after WrapperFun1 after WrapperFun1 None
你困惑的重复执行序列,本质是两次嵌套调用了WrapperFun1,下面一步步拆解执行逻辑:
1. 装饰器语法糖的初始化执行
当你用@DecoratorFun修饰TestFun时,Python会自动执行DecoratorFun(原始TestFun):
- 打印
DecoratorFun is called(这是输出的第一行) - 定义
WrapperFun1和WrapperFun2,但由于return WrapperFun1在WrapperFun2之前,WrapperFun2的定义和后续代码永远不会被执行,直接被忽略 - 将
TestFun的指向替换为返回的WrapperFun1——此时全局的TestFun已经不是你最初定义的那个打印In Test Function的函数了,而是WrapperFun1
2. 关键语句print(DecoratorFun(TestFun)())的执行
这一行是触发重复输出的核心,拆成三步看:
2.1 调用DecoratorFun(TestFun)
这里传入的TestFun已经是第一步中被替换后的WrapperFun1,所以:
- 再次打印
DecoratorFun is called(你的输出里可能漏了这一行,不过不影响核心逻辑) - 再次定义
WrapperFun1并返回它
2.2 调用返回的WrapperFun1()
此时执行这个新的WrapperFun1:
- 打印
In DecoratorFun and WrapperFun1(这是重复序列的第一行) - 调用
func()——这里的func是传入的TestFun,也就是第一步中被替换后的旧WrapperFun1
2.3 调用旧WrapperFun1()
此时执行旧的WrapperFun1:
- 打印
In DecoratorFun and WrapperFun1(重复序列的第二行) - 调用
func()——这里的func是最开始的原始TestFun- 打印
In Test Function
- 打印
- 打印
after WrapperFun1(重复序列的第四行)
2.4 回到新WrapperFun1()的执行
执行完旧WrapperFun1后,回到新WrapperFun1:
- 打印
after WrapperFun1(重复序列的第五行)
3. 最后打印返回值
由于WrapperFun1没有定义返回值,默认返回None,所以最后一行输出None
另外补充:你代码里的WrapperFun2确实永远不会被执行,因为return WrapperFun1语句会直接跳出DecoratorFun函数,后面的代码都不会运行。
内容的提问来源于stack exchange,提问作者Giridhar
相关产品推荐
相关产品推荐

