1.
import time, datetime class Ly: def __init__(self, fun): self.fun = fun print('this is the first step on ' + str(datetime.datetime.now())) time.sleep(1) self.fun() def __call__(self): print('this is the thirty step on ' + str(datetime.datetime.now())) time.sleep(1) @Ly def show(): print('this is the second step on ' + str(datetime.datetime.now())) time.sleep(1) if __name__ == "__main__": show() print('this is the fourth step on ' + str(datetime.datetime.now()))
2.
import time class Ly(object): def __init__(self, fun): print("this is the first step") time.sleep(1) self.fun = fun def __call__(self, *args): print("this is the second step") time.sleep(1) self.fun(*args) print("this is the fourth step") time.sleep(1) @Ly def show(a1, a2, a3, a4): print('this is the thirty step', a1, a2, a3, a4) time.sleep(1) show("parm", "1", "1", "1") print("After first part call") time.sleep(1) show("parm", "2", "2", "2") print("After second part call")
从中可以发现:
(1).只要有被类装饰器装饰的对象,类装饰器的 __init__ 函数就会执行(不需要调用)
(2).被类装饰器装饰的函数不论被调用几次,__init__ 函数只会执行一次,并且它的执行是被装饰函数声明装饰时就自动执行,不需要手动调用
(3).当被装饰函数存在参数时,从 __call__ 函数传进参数(不必须 *args,但这是一种规范 def __call__(self,*args,**kwargs))
*args是指字符串,**kwargs是指字典
3.
import time class Ly: def __init__(self, one_parm, two_parm, three_parm): self.one_parm = one_parm self.two_parm = two_parm self.three_parm = three_parm def __call__(self, fun): print('性别为' + self.one_parm + "的" + self.two_parm + "岁的" + self.three_parm) time.sleep(1) def info(*args): fun(*args) return info @Ly("男", "22", "ly") def show(name, age, sex): print('性别为' + sex + "的" + age + "岁的" + name) show("蓝月", "20", "男")
注意:
(1).装饰器有装饰器的参数,函数(被装饰器修饰的函数)有函数的参数,不可混淆
(2).装饰器函数的参数从 __init__ 函数中传,函数的参数从 __call__ 函数中传
python多个装饰器的执行顺序
def decorator_a(func): print 'Get in decorator_a' def inner_a(*args, **kwargs): print 'Get in inner_a' return func(*args, **kwargs) return inner_a def decorator_b(func): print 'Get in decorator_b' def inner_b(*args, **kwargs): print 'Get in inner_b' return func(*args, **kwargs) return inner_b @decorator_b @decorator_a def f(x): print 'Get in f' return x * 2 f(1)
执行如上所示代码,最后的执行结果为:
Get in decorator_a
Get in decorator_b
Get in inner_b
Get in inner_a
Get in f
我们来分析下,为什么会是这样的顺序(验证的过程中可以通过打断点的方式来观察函数的程序的执行流程)。
首先:
1、装饰器函数在被装饰函数定义好后立即执行。
我们把代码最后一行注掉:
# f(1)
重新执行,会发现最后执行结果为:
Get in decorator_a
Get in decorator_b
说明装饰器函数在被装饰函数定义好后就立即执行。而且执行顺序是由下到上开始装饰。调用decorator_a时,f被装饰成inner_a,调用decorator_b时,f被装饰成inner_b。
通过在最后执行:print(f), 执行结果为<function inner_b at 0x00000000038F15F8>可验证。
所以如上所示代码中,最后执行f(1)时,f已经变成了inner_b,而inner_b中return的func,实则为inner_a, inner_a中return的func才是最终的f。
所以最后的调用顺序为
inner_b --->inner_a--->f
执行结果为:
Get in inner_b
Get in inner_a
Get in f
在实际应用的场景中,当我们采用上面的方式写了两个装饰方法比如先验证有没有登录 @login_required , 再验证权限够不够时 @permision_allowed 时,我们采用下面的顺序来装饰函数:
@login_required @permision_allowed def f() # Do something return
总结一下:
多个装饰器装饰函数时,有个规律是从小到上包裹(装饰)函数,从上到下执行。
原文:https://blog.csdn.net/qq_35462323/article/details/90633796