多个装饰器的执行顺序"/>
Python多个装饰器的执行顺序
看了好多相关文章,也有些有错误,还是自己记录一下吧.
def decrator_a(func):print("enter decrator_a")def inner_a(*args,**kwargs):print("enter inner_a")ret = func(*args,**kwargs)print("leaving inner_a")return retprint("leaving decrator_a")return inner_adef decrator_b(func):print("enter decrator_b")def inner_b(*args,**kwargs):print("enter inner_b")ret = func(*args,**kwargs)print("leaving inner_b")return retprint("leaving decrator_b")return inner_b@decrator_a
@decrator_b
def f(*args,**kwargs):print("==f==")
#相当于decrator_a(decrator_b(f))
f()
执行结果为:
>>>
RESTART: C:/Users/Administrator/AppData/Local/Programs/Python/Python36/tests/decrator_test.py
enter decrator_b
leaving decrator_b
enter decrator_a
leaving decrator_a
enter inner_a
enter inner_b
==f==
leaving inner_b
leaving inner_a
解释一下顺序
明确两点 一是装饰器的执行顺序从下往上,函数调用时从上往下. 二是装饰器函数在被装饰函数定义好后立即执行
一好理解,二的意思就是说即使f没有执行,上面的装饰器函数还是会执行(可以把f()删掉直接运行一下试试)
首先例子中的装饰器顺序相当于decrator_a(decrator_b(f)), 而decrator_b(f)返回的就是一个函数,如此循环的话,在多个装饰器也可以看成只有最外层的一个.另外函数f经过装饰器装饰后,函数f = decrator_a(decrator_b(f)),
然后根据装饰器的特点,执行顺序从近到远,或者说由下而上,先执行decrator_b(f),看代码,先打印一个①"enter decrator_b",然后定义了一个函数inner_b, 返回值为f的执行结果,然而,这个inner_b这个函数并没有被调用,所以相当于一个pass,可以暂时跳过,然后打印一个②"leving decrator_b", 并返回一个函数inner_b,这时候返回这个函数,返回的是函数,而不是函数的执行结果,所以此时inner_b函数还是没有执行,只是 被返回了
这时就变成了decrator_a(inner_b),跟据代码,也是先打印③"enter decrator_a", 然后也是定义一个函数inner_a,同样当成是pass,然后打印④"leaving decrator_a", 然后返回inner_a,
如果没有f()这行,会返回这个结果,会打印四行,分别是
enter decrator_b
leaving decrator_b
enter decrator_a
leaving decrator_a
加上f()这行之后,就开始执行函数了
因为此时函数f是经过装饰器装饰过的了, f = inner_a, f() = inner_a()
然后再来看函数inner_a, 相当于
def inner_a(*args,**kwargs):print("enter inner_a")ret = inner_b(*args,**kwargs)print("enter inner_a")return ret
所以这时候打印一个"enter inner_a", 然后执行inner_b并把结果赋值给变量ret, inner_b执行时打印一句"enter inner_b", 然后开始执行函数f,这个函数f是还没有经过装饰器装饰的函数,(相当于 a = 1 a = a +1 ,a = a +1 中等号后面的a还是原来的a=1),所以应该打印一行⑤" =f=", 这时函数f执行完了,返回上一级的inner_b中,继续执行,打印一行⑥"leaving inner_b", 然后返回inner_b中的ret,因为函数f没有返回值,所以返回None, 再往上一级返回inner_a中,ret = None,打印一行⑦"leaving inner_a",最后返回ret,也就是None, 这里并没有打印返回结果,所以None不会在打印结果中出现.
更多推荐
Python多个装饰器的执行顺序
发布评论