写作思路
本文主要讲述装饰器的使用以及装饰器整个运行流程的顺序!!!
1、简易装饰器及运行顺序的分析
2、双层装饰器及运行顺序的分析
3、总结
1、简易装饰器
①被包裹函数内的执行顺序
# -*- coding: utf-8 -*-
from functools import wraps
def MyDecorator(func):
def wrapper(arg1, arg2, arg3):
print("run in decorator before func", arg1, arg2, arg3)
func(arg1, arg2, arg3)
print("run in decorator after func", arg1, arg2, arg3)
return wrapper
@MyDecorator
def test(a, b, c):
print("run in function", a, b, c)
if __name__ == '__main__':
test(10, 20, 30)
运行结果如下
基于上述结果,我们不难看出,被装饰函数的运行其实就是装饰器内func的运行位置,基于上述思想,我们还可以把 func 放在装饰器内的任意位置,比如下面这样
②被包裹函数的外层上方
def MyDecorator(func):
func(100, 200, 300)
def wrapper(arg1, arg2, arg3):
print("run in decorator before func", arg1, arg2, arg3)
func(arg1, arg2, arg3)
print("run in decorator after func", arg1, arg2, arg3)
return wrapper
运行结果:
或者这样
③被包裹函数的外层下方
def MyDecorator(func):
def wrapper(arg1, arg2, arg3):
print("run in decorator before func", arg1, arg2, arg3)
func(arg1, arg2, arg3)
print("run in decorator after func", arg1, arg2, arg3)
func(100, 200, 300)
return wrapper
运行结果:
哈哈哈哈 看到没有 上面的运行结果是一样的!!千万别掉坑里去,因为wrapper是返回的函数,因此他要在返回之后才会被调用!所以外层的函数一定是会先执行的!!!
2、双层装饰器
①装饰器外层如果有方法时的深层分析
# -*- coding: utf-8 -*-
from functools import wraps
def DoubleDecorator(flagStr, name=None, message=None):
print("1111111", flagStr, name, message)
def decorate(func):
print("2222222", flagStr, name, message)
@wraps(func)
def wrapper(arg1, arg2):
print("3333333", flagStr, name, message)
res = func(arg1, arg2)
print("4444444", flagStr, name, message)
return res
return wrapper
print("5555555", flagStr, name, message)
return decorate
@DoubleDecorator("True", "addFunction", "run by add")
def add(x, y):
print("run in add function", x, y)
return x + y
if __name__ == '__main__':
# print("run in main thread ", add(1, 2))
pass
注意看哇,此时我们是没有调用被装饰的函数 add的!!
但是运行结果如下:
先别急着做分析,我们再回过头来看看上一个例子,此时我们做同样的处理
# -*- coding: utf-8 -*-
from functools import wraps
def MyDecorator(func):
def wrapper(arg1, arg2, arg3):
print("run in decorator before func", arg1, arg2, arg3)
func(arg1, arg2, arg3)
print("run in decorator after func", arg1, arg2, arg3)
func(100, 200, 300)
return wrapper
@MyDecorator
def test(a, b, c):
print("run in function", a, b, c)
if __name__ == '__main__':
# test(10, 20, 30)
pass
运行结果如下:
只要我们使用了装饰器,那么不管这个函数是否被调用,装饰器外层的方法都会运行的!并且装饰了几个函数就会运行几次!!!
②双层装饰器的运行顺序
if __name__ == '__main__':
print("run in main thread ", add(1, 2))
运行结果如下:
分析可知:包裹在越内层的函数,被调用的时机就越晚,就和我们最上面简易的装饰器是一样的!
PS.记得在最内层要把res返回,不然在main运行的输出会打印出None哦!
3、总结
1、被装饰的函数无论是否调用,装饰器外层的方法都会被运行
2、装饰器的越外层的函数会越早被运行(其实就是很正常的事,但是脑子一热就忘记了)
3、对于有返回值的被装饰函数,记得要在内层把值返回,不然被装饰函数的工作就白做啦!(当然你要是只想在装饰器内得到被装饰函数的返回值我也没意见)