装饰器函数的执行顺序是分为(被装饰函数)定义阶段和(被装饰函数)执行阶段的,装饰器函数在被装饰函数定义好后立即执行
- 在函数定义阶段:执行顺序是从最靠近函数的装饰器开始,自内而外的执行
- 在函数执行阶段:执行顺序由外而内,一层层执行
def war1(func):
print("war1")
def inner(*args, **kwargs):
print("======war1 start=====")
func(*args, **kwargs) #inner
print("======war1 end=====")
return inner
def war2(func):
print("war2")
def inner(*args,**kwargs):
print("======war2 start=====")
func(*args,**kwargs)
print("======war2 end=====")
return inner
@war1
@war2
def f():
print("****self****")
f()
- 执行结果
那么为什么会是这样的顺序
看到这个执行结果,我们可能会疑惑,为什么先打印了war2 和war1呢?
首先要知道,装饰器函数在被装饰函数定义好后就立即执行了
我们去掉函数执行,只留下函数的定义,代码如下:
def war1(func):
print("war1")
def inner(*args, **kwargs):
print("======war1 start=====")
func(*args, **kwargs) #inner
print("======war1 end=====")
return inner
def war2(func):
print("war2")
def inner(*args,**kwargs):
print("======war2 start=====")
func(*args,**kwargs)
print("======war2 end=====")
return inner
@war1
@war2
def f():
print("****self****")
结果
也就是说在 f 方法没有执行的时候,装饰器函数就执行了
此处我们需要先弄清楚,函数和函数调用的区别,f 是一个函数,它的值是函数本身, f( )是函数的调用,它的值是函数的执行结果
在被装饰函数定义阶段,也就是函数调用之前:
而
@war1
@war2
def f():
print("****self****")
上面代码相当于执行
war1(war2(f))
在综合起来就是相当于执行了先打印war2war1
,再执行函数war1(war2(f))
按照这样的顺序执行,层层包裹
执行方式
war2-->war1--> war1-->war2-->f -->war2-->war1
所以最终结果为
同理对于三个装饰器
三个装饰器对应两个函数
可以看到f2并没有用到装饰器
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def f(n):
def out_wrapper(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
return out_wrapper
n=5
@f(n) #@f(n=5)或者@f(5)都是错的,会显示n未定义
def p(x):
return x * n
p(4)
其实就是实现下面代码的效果
def f(n):
def g(x):
return n*x
return g
f1=f(5)
f1(4)
法二:
def f(n):
def warpper(func):
def q23(*args, **kw):
return func(*args, **kw)*n
return q23
return warpper
@f(n=1200)#或者n=1200,@f(n)
def p(x):
return x
print(p(6))
法三:
from functools import partial
def f(func=None, *, n):
if func is None:
return partial(f, n=n)
def wrapper(*args, **kwargs):
return func(*args, **kwargs) * n
return wrapper
@f(n=5)
def p(x):
return x
p(4)