当前位置: 移动技术网 > IT编程>脚本编程>Python > python装饰器

python装饰器

2018年05月15日  | 移动技术网IT编程  | 我要评论

别惹大魔王2,史大平,料理机和榨汁机的区别

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

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网