python装饰器
1.什么是装饰器
简单说就是在被装饰的函数前后增加新功能,
而不用修改函数内部结构和调用方式的特殊语法
def out(fun):
def inner():
print('函数前新增功能...')
fun()
print('函数后新增功能...')
return inner
@out
def test():
print('---test---')
test()
输出
函数前新增功能... ---test--- 函数后新增功能...
此时的@out就是装饰器,
同时也可以看到装饰器只能在被修饰函数整体的前后[增加]功能,
而不能[修改]被装饰的函数的功能
2.装饰器的执行顺序
补充:
1.函数执行的顺序是由上自下,由右至左
2.函数名仅仅是一个变量而已
3.@out等价于test = out(test)
当执行到@out时,三个小步骤
- 向
out函数传递被装饰函数的引用,并用形参fun指向此时变量test指向的函数引用 - 执行装饰器外层函数
out(),获得内层变量inner指向的函数的引用 - 改变被装饰函数的指向,让此时变量
test指向inner函数的引用
3.通用装饰器的基本结构
def out(fun):
def inner(*args, **kwargs):
print('函数前新增功能...')
fun(*args, **kwargs)
print('函数后新增功能...')
return inner
4.用多个装饰器装饰一个函数
def first(first_func): # first_func 记录了第二次 test 指向,即 final_inner 的引用 ,print('---final-2---')和final_func()
print('---first-1---')
def first_inner():
print('---first-2---')
first_func()
return first_inner
def final(final_func): # final_func 记录了第一次 test 指向,即print('---test---')
print('---final-1---')
def final_inner():
print('---final-2---')
final_func()
return final_inner
@first # test = first(test) 第二次改变的test指向first_inner,从右向左执行
@final # test = final(test) 第一次改变的test指向final_inner,从右向左执行
def test():
print('---test---')
test()
结果
---final-1--- ---first-1--- ---first-2--- ---final-2--- ---test---
实际的执行顺序:
- 先执行
@first装饰器,但是@first下面没有函数,则等待下面语句获得函数时再接着执行 - 再执行
@final装饰器,打印[---final-1---],将被装饰的函数test的引用传递给形参final_func记录, - 然后返回
final_inner函数的引用(第一次改变test的指向)给变量test - 此时
@first下面有了函数test,接着去执行@first装饰器,打印[---first-1---],将此时test记录的final_inner的引用传递给形参first_func记录, - 并将
first_inner的引用给了变量test(第二次改变test指向) - 最后执行
test(),此时test记录的是first_inner的引用,相当于执行first_inner(),打印[---first-2---] - 然后执行
first_func(),first_func存的是final_inner的引用,相当于执行力final_inner(),打印[---final-2---] - 此时执行
final_func(),final_func存的是test最开始的引用,打印[---test---]
看上去是:
先执行了后一个的装饰器的的外层函数final
然后执行前一个装饰器的外层函数first
然后执行前一个装饰器first_inner
接着执行后一个函数的内部函数final_inner
最后执行test本身
5.类-装饰器简单总结
如果一个类重写了__call__()方法,那么这个类可以被用作装饰器,称为类装饰器
类装饰器的基本形式
class A(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print('函数前新增功能...')
self.func()
print('函数后新增功能...')
@A # test = A(test) 以A类为模板,创建实例对象test
def test():
print('---test---')
test()
6.含有参数的装饰器
def out_out(x):
def out(fun):
def inner(*args, **kwargs):
print('函数前新增功能...%s' % x)
fun(*args, **kwargs)
print('函数后新增功能...%s' % x)
return inner
return out
@out_out('测试') # 相当于 test = out_out(111)(test)
def test():
print('---test---')
7.装饰器的功能作用
- 引入日志
- 函数执行时间统计
- 执行函数前预备处理
- 执行函数后清理功能
- 权限校验等场景
- 缓存
来源:https://www.cnblogs.com/spirit911/p/9038925.html