欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python装饰器

程序员文章站 2022-10-06 19:07:21
python装饰器 1.什么是装饰器 简单说就是在被装饰的函数前后增加新功能, 而不用修改函数内部结构和调用方式的特殊语法 输出 此时的 就是装饰器, 同时也可以看到装饰器只能在被修饰函数整体的前后[增加]功能, 而不能[修改]被装饰的函数的功能 2.装饰器的执行顺序 补充: 1.函数执行的顺序是由 ......

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.装饰器的功能作用

  • 引入日志
  • 函数执行时间统计
  • 执行函数前预备处理
  • 执行函数后清理功能
  • 权限校验等场景
  • 缓存