zoukankan      html  css  js  c++  java
  • 多层装饰器执行顺序

    一、叠加多个装饰器

    加载顺序:自下而上
    运行顺序:自上而下

    代码:

    def deco1(func1):   #func1=wrapper2的内存地址
        print('装饰器1')
        def wrapper1(*args,**kwargs):
            print('wrapper1===>')
            res1=func1(*args,**kwargs)
            return res1
        return wrapper1
    
    
    def deco2(func2): #func2= wrapper3的内存地址
        print('装饰器2')
        def wrapper2(*args,**kwargs):
            print('wrapper2===>')
            res2=func2(*args,**kwargs)
            return res2
        return wrapper2
    
    
    def deco3(func3):          #func3=最原始的那个被装饰函数的内存地址
        print('装饰器3')
        def wrapper3(*args,**kwargs):
            print('wrapper3===>')
            res3=func3(*args,**kwargs)
            return res3
        return wrapper3
    
    
    @deco1   #deco1(wrapper2的内存地址)=》wrapper1的内存地址
    @deco2   #deco2(wrapper3的内存地址)=》wrapper2的内存地址
    @deco3   #deco3(最原始的那个被装饰函数的内存地址)=》wrapper3的内存地址
    def index(x,y):
        print('index==>',x,y)


    index(1,2)

    运行结果

    装饰器3
    装饰器2
    装饰器1
    wrapper1===>
    wrapper2===>
    wrapper3===>
    index==> 1 2




    那么为什么会是这样的顺序???

    
    

    看到这个执行结果,我们可能会疑惑,为什么先打印了装饰器3,装饰器2,装饰器1呢?

    我们去掉函数执行,只留下函数的定义,代码如下:

    def deco1(func1):   #func1=wrapper2的内存地址
        print('装饰器1')
        def wrapper1(*args,**kwargs):
            print('wrapper1===>')
            res1=func1(*args,**kwargs)
            return res1
        return wrapper1
    
    
    def deco2(func2): #func2= wrapper3的内存地址
        print('装饰器2')
        def wrapper2(*args,**kwargs):
            print('wrapper2===>')
            res2=func2(*args,**kwargs)
            return res2
        return wrapper2
    
    
    def deco3(func3):          #func3=最原始的那个被装饰函数的内存地址
        print('装饰器3')
        def wrapper3(*args,**kwargs):
            print('wrapper3===>')
            res3=func3(*args,**kwargs)
            return res3
        return wrapper3
    
    
    @deco1   #deco1(wrapper2的内存地址)=》wrapper1的内存地址
    @deco2   #deco2(wrapper3的内存地址)=》wrapper2的内存地址
    @deco3   #deco3(最原始的那个被装饰函数的内存地址)=》wrapper3的内存地址
    def index(x,y):
        print('index==>',x,y)

    执行结果:

    装饰器3
    装饰器2
    装饰器1

    也就是说在index方法没有执行的时候,装饰器函数就执行了

    此处我们需要先弄清楚,函数和函数调用的区别,index是一个函数,它的值是函数本身,index()是函数的调用,它的值是函数的执行结果。

    在被装饰器函数定义阶段,也就是函数调用之前

    @deco1   #deco1(wrapper2的内存地址)=》wrapper1的内存地址
    @deco2   #deco2(wrapper3的内存地址)=》wrapper2的内存地址
    @deco3   #deco3(最原始的那个被装饰函数的内存地址)=》wrapper3的内存地址
    def index(x,y):
        print('index==>',x,y)

    这段代码相当于:

    deco1(deco2(deco3(index)))

    deco1和deco2和deco3的返回值都是一个函数,所以deco1(deco2(deco3(index)))也是一个函数,deco1包含了deco2,deco2包含了deco3

    index(1,3)相当于deco1(deco2(deco3(index)))()

    所以index()在执行时,deco3--》deco2--》deco1--》deco1--》deco2--》deco3--》index--》deco3--》deco2--》deco1按照这样的顺序执行

  • 相关阅读:
    二:dot语言语法及使用
    一:安装graphviz
    一个程序的前世今生(四)——延迟绑定和GOT与PLT
    一个程序的前世今生(三)——动态链接库和静态链接库
    一个程序的前世今生(二)——可执行文件如何加载进内存
    更新mysql驱动5.1-47 Generated keys not requested. You need to specify Statement.RETURN_GENERATED_KEY
    The superclass javax servlet http HttpServlet was not found on the Java Build Path
    vue-router地址栏URL全局参数拼接
    Canvas签字画图板
    Vue 表单拖拽排序
  • 原文地址:https://www.cnblogs.com/ltyc/p/14453913.html
Copyright © 2011-2022 走看看