一、装饰器
本身就是函数,都是用def语法来定义的,为其他函数添加附加功能。
二、应用场景
假设目前编写的函数已经上线运行了,某一天,产品有个需求,要在这个里面新增一个功能,那怎么去做这个事?最简单的就是:重新编码。但是问题是程序已经运行了,修改程序源码,会有风险发生。
所以说,我要新增一个功能,不能够修改函数的源代码,且不改变原函数的调用方式,这个时候装饰器就出现了
闭包
要了解装饰器首先要知道什么是闭包
总结起来就是:
1、外层函数返回了内存函数的引用
2、内层函数引用了外层函数的参数
1 def out(num): #外层函数
2 print('1')
3 def inner(): #内层函数
4 print(num)
5 print('5')
6 print('2')
7 return inner #返回了内层函数的引用
8
9 res = out(4)
10 res()
这就是闭包,那么闭包是怎么执行的呢
1 2 4 5
当调用out() 的时候,此时执行外层函数,输出1,输出2 ,注意:当程序执行到第3行时,只是在此声明了一个函数,并没有做任何事情,此时res接收了out的返回值(inner函数的引用)
当调用res() 的时候,此时相当于调用inner函数,输出4,输出5,执行完毕
执行内部函数的时候,外层函数的变量并没有被销毁,可以一直被调用。
def out(num): print('1') def inner(num_inner): print(num) print(num_inner) print('2') return inner res = out(4) res(11) res(22) res(33) res(44)
此时输出结果为
1 2 4 11 4 22 4 33 4 44
此种应用,虽然编写函数的时候会稍微麻烦点,但是可以反复调用,不会被释放,传参数的时候也可以简化
装饰器
1、只是在原来的函数基础上增加新的函数,达到在执行原来的函数之前或者之后执行新添加的功能
2、不改变原函数的调用方式,原来调用哪个函数现在还调用哪个函数
示例一:
def out1(func): #此函数相当于拓展函数 print('外层开始执行') def inner1(): print('内层开始执行') func() print('外层执行完毕') return inner1
@out1 def ma(): #此函数相当于原来的函数 print('这是一个主函数') ma() #调用方式依旧是原来的调用
输出结果
外层开始执行
外层执行完毕
内层开始执行
这是一个主函数
示例二:
def out1(canshu): print('外层开始执行') def inner1(): print('内层开始执行') canshu() print('外层执行完毕') return inner1 # @out1 def ma(): print('这是一个主函数') ma = out1(ma) ma()
输出结果
外层开始执行
外层执行完毕
内层开始执行
这是一个主函数
可以看到上面两种方式实现了同样的功能(示例一属于闭包函数装饰了原来的函数)
可以看出
ma = out1(ma)
ma()
只是被 语法糖 @out1 替换掉了
在函数ma上面加上了@out1,就相当于 out1(ma)
当程序执行到@定义的位置,就会自动执行闭包体的外层函数,当执行到原函数调用时,会自动执行闭包体的内层函数
下面附上详细图片