python 中多个装饰器的执行顺序

  • 装饰器函数在被装饰函数定义好后立即执行。多个装饰器的调用顺序是自下往上的。

  • 被装饰函数执行时,装饰器的执行顺序是从上往下的。

案例一:

案例脚本:


def wrapper1(f1):
    print('in wrapper1')
    def inner1(*args,**kwargs):
        print('in inner1')
        ret = f1(*args,**kwargs)
        return ret
    return inner1
 
def wrapper2(f2):
    print('in wrapper2')
    def inner2(*args,**kwargs):
        print('in inner2')
        ret = f2(*args,**kwargs)
        return ret
    return inner2
 
def wrapper3(f3):
    print('in wrapper3')
    def inner3(*args,**kwargs):
        print('in inner3')
        ret = f3(*args,**kwargs)
        return ret
    return inner3
 
@wrapper1
@wrapper2
@wrapper3
def func():
    print('in func')
func()
# in wrapper3
# in wrapper2
# in wrapper1
# in inner1
# in inner2
# in inner3
# in func
#装饰器函数在被装饰函数定义好后立即执行。多个装饰器的调用顺序是自下往上的。
# 被装饰函数执行时,装饰器的执行顺序是从上往下的。

运行结果:

in wrapper3
in wrapper2
in wrapper1
in inner1
in inner2
in inner3
in func

Process finished with exit code 0

结果分析:

分析
先执行@wrapper3  等于 func = wrapper3(func) ---> 先打印'in wrapper3', 返回 inner3(把这个作为参数传给wrapper2) 【f3 = func】
在执行@wrapper2  等于执行  wrapper2(inner3) ---> 先打印'in wrapper2', 返回 inner2(把这个作为参数传给wrapper1)  【f2 = inner3】
在执行@wrapper1  等于执行  wrapper1(inner2) ---> 先打印'in wrapper2', 返回 inner1
此时func = inner1 【f1 = inner2】
运行func() 等价于执行inner1()  ---> 先打印'in inner1'  再执行f1() 【装饰器中wrapper1(f1),实际 wrapper1(inner2),所以f1=inner2  可以理解f1是形参,inner2是实参】 
再运行inner2()  ---> 先打印'in inner2' 再执行f2()  f2=inner3
再运行inner3()  --->先打印'in inner3' 再执行f3()     f3=func
再运行func()  --->先打印'in func'

ChatGPT回答

 这段代码中,装饰器的执行顺序是从下往上执行,即最后一个装饰器先执行,然后依次向上执行。具体的执行顺序如下:

1. wrapper3 装饰器先执行,打印 "in wrapper3"。
2. wrapper2 装饰器接收 wrapper3 装饰后的函数作为参数,打印 "in wrapper2"。
3. wrapper1 装饰器接收 wrapper2 裰饰后的函数作为参数,打印 "in wrapper1"。
4. 最终,func 函数被依次传入 wrapper1、wrapper2、wrapper3 装饰器,形成装饰链,执行顺序为 wrapper3 -> wrapper2 -> wrapper1。

因此,当调用 func() 函数时,会按照上述装饰器的执行顺序,依次执行 inner3 -> inner2 -> inner1 -> func,并打印相应的信息。

案例二:

脚本案例: 

# encoding: utf-8
# @File  : test10.py
# @Author: wu shaofan
# @Date  :  2024/02/09
# @Desc :

from time import sleep, time


def mylog(func):
    print("mylog, start")

    def infunc2():
        print("日志记录, start")
        func()
        print("日志记录, end")

    print("mylog, end")
    return infunc2


def cost_time(func):
    print("cost_time start")

    def infunc1():
        print("开始计时")
        start = time()
        func()
        end = time()
        print(f"耗费时间:{end - start}")

    print("cost_time end")
    return infunc1



# mylog(cost_tine(fun2))
@mylog
@cost_time
def func2():
    print("func2, start")
    sleep(3)
    print("func2, end")


func2()

运行结果:

cost_time start
cost_time end
mylog, start
mylog, end
日志记录, start
开始计时
func2, start
func2, end
耗费时间:3.009023904800415
日志记录, end

Process finished with exit code 0

结果分析:

  1. 在函数定义阶段:执行顺序是从最靠近函数的装饰器开始,自内而外的执行

  2. 在函数执行阶段:执行顺序由外而内,一层层执行

从靠近函数的装饰器开始执行:

先进到cost_time,print("cost_time start"),print("cost_time end"),返回infunc1, 把这个作为参数传给mylog,进到mylog里面, print("mylog, start"),print("mylog, end"),返回infunc2,进到infunc2里面,print("日志记录, start"),运行func(),此时因为参数是infunc1,所以进到infunc1里面,print("开始计时"),运行func(),它的参数是func2,所以进到func2,print("func2, start"),print("func2, end"),再接下去print(f"耗费时间:{end - start}"),把infunc1运行完了,回到infunc2,print("日志记录, end")。 

先执行@cost_time 等于 func2 = cost_time(func2) ---> 先打印'cost_time start'和"cost_time end" 返回 infunc1(把这个作为参数传给mylog)  func2 = infunc1

在执行@mylog 等于 func2 = mylog(infunc1) ---> 先打印'mylog, start'和"mylog, end" 返回 infunc2

此时 func2 = infunc2

运行func2() 即运行infunc2() ---> 先打印'日志记录, start' 再执行func(),等于执行infunc1() 还没完

进入infunc1() ---> 先打印'开始计时' 再执行func() 等于执行func2() 还没完

进入func2() ---> 先打印'func2, start' 和 "func2, end" 退出func2函数 ,

再回到infunc1() ---> 先打印"耗费时间:{end - start}" 退出infunc1函数

再回到infunc2() ---> 先打印"日志记录, end" 退出infunc2函数

结束

图片比较直观:

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python,如果一个函数使用了多个装饰器,那么它们的执行顺序是从下往上的。也就是说,最下面的装饰器最先执行,最上面的装饰器最后执行,函数执行完后,装饰器执行顺序则与装饰器定义的顺序相反。 例如,下面是一个使用三个装饰器的示例: ``` python def decorator1(func): def wrapper(*args, **kwargs): print("Decorator 1 before function execution") func(*args, **kwargs) print("Decorator 1 after function execution") return wrapper def decorator2(func): def wrapper(*args, **kwargs): print("Decorator 2 before function execution") func(*args, **kwargs) print("Decorator 2 after function execution") return wrapper def decorator3(func): def wrapper(*args, **kwargs): print("Decorator 3 before function execution") func(*args, **kwargs) print("Decorator 3 after function execution") return wrapper @decorator1 @decorator2 @decorator3 def my_function(): print("Function execution") my_function() ``` 输出结果为: ``` Decorator 3 before function execution Decorator 2 before function execution Decorator 1 before function execution Function execution Decorator 1 after function execution Decorator 2 after function execution Decorator 3 after function execution ``` 可以看到,装饰器3最先执行,然后是装饰器2,最后是装饰器1。而函数执行完后,装饰器执行顺序则与装饰器定义的顺序相反,即装饰器1最先执行,然后是装饰器2,最后是装饰器3。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值