多层装饰器执行顺序

一、叠加多个装饰器

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

代码:

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按照这样的顺序执行

原文地址:https://www.cnblogs.com/ltyc/p/14453913.html