• python_装饰器


    一,什么是装饰器?

      装饰器本质上就是一个python函数,他可以让其他函数再不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象.

    装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景.

    二,装饰器的形成过程.

    现在我又一个需求我想躺你测试这个函数的执行时间,在不改变这个函数代码的情况下:

    import time
    
    def func1():
        print('in func1')
    
    def timer(func):
        def inner():
            start = time.time()
            func()
            print(time.time() - start)
        return inner
    
    func1 = timer(func1)
    func1()

    但是如果有多个函数,我都想让你测试他们的执行时间,你每次是不是都的func1=timer(func1)?

    这样还是有点麻烦.因为这些函数的函数名可能是不相同,有func1,func2等等,

    所以更简单的方法,python给你提供了,那就是语法糖

    import time
    def timer(func):
        def inner():
            start = time.time()
            func()
            print(time.time() - start)
        return inner
    
    @timer   #==> func1 = timer(func1)
    def func1():
        print('in func1')
    
    
    func1()
    View Code

    刚刚我们讨论的装饰器都是装饰不带参数的函数,现在要装饰一个带参数的函数怎么办?

    def timer(func):
        def inner(a):
            start = time.time()
            func(a)
            print(time.time() - start)
        return inner
    
    @timer
    def func1(a):
        print(a)
    
    func1(1)
    装饰器--带参数的装饰器
    import time
    def timer(func):
        def inner(*args,**kwargs):
            start = time.time()
            re = func(*args,**kwargs)
            print(time.time() - start)
            return re
        return inner
    
    @timer   #==> func1 = timer(func1)
    def func1(a,b):
        print('in func1')
    
    @timer   #==> func2 = timer(func2)
    def func2(a):
        print('in func2 and get a:%s'%(a))
        return 'fun2 over'
    
    func1('aaaaaa','bbbbbb')
    print(func2('aaaaaa'))
    装饰器--无敌的接受所有的

    上面的装饰器已经非常完美了,但是我们正常情况下查看函数信息的方法在此处都会丢失效果:

    def index():
        '''这是一个主页信息'''
        print('from index')
    
    print(index.__doc__)    #查看函数注释的方法
    print(index.__name__)   #查看函数名的方法
    

      如何解决呢?

    from functools import wraps
    
    def deco(func):
        @wraps(func) #加在最内层函数正上方
        def wrapper(*args,**kwargs):
            return func(*args,**kwargs)
        return wrapper
    
    @deco
    def index():
        '''哈哈哈哈'''
        print('from index')
    
    print(index.__doc__)
    print(index.__name__)

    三,开放封闭原则.

      1.对扩展是开放的

        为什么要对扩展开放呢?

        我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何

      更信和修改.所以我们必须允许代码扩展,添加新功能.

      2.对修改是封闭的

        为什么要对修改封闭呢?

         就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给他人舒勇了,

      如果这个时候我们对其进行修改,很有可能影响其他已经在使用的该函数的用户.

      装饰器完美的遵循的这个开放封闭原则.

    四.装饰器的主要功能个固定结构.

    def timer(func):
        def inner(*args,**kwargs):
            '''执行函数之前要做的'''
            re = func(*args,**kwargs)
            '''执行函数之后要做的'''
            return re
        return inner
    装饰器--固定格式
    from functools import wraps
    
    def deco(func):
        @wraps(func) #加在最内层函数正上方
        def wrapper(*args,**kwargs):
            return func(*args,**kwargs)
        return wrapper
    装饰器--固定格式-wraps版

    五.带参数的装饰器.

      假如你有成千上万个函数使用一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做?

      一个一个取消掉?,没日没夜忙活3天...

      过两天你领导想通了再让你加上...

    def outer(flag):
        def timer(func):
            def inner(*args,**kwargs):
                if flag:
                    print('''执行函数之前要做的''')
                re = func(*args,**kwargs)
                if flag:
                    print('''执行函数之后要做的''')
                return re
            return inner
        return timer
    
    @outer(False)
    def func():
        print(111)
    
    func()
    带参数的装饰器

    六,多个装饰器装饰一个函数.

    def wrapper1(func):
        def inner():
            print('wrapper1 ,before func')
            func()
            print('wrapper1 ,after func')
        return inner
    
    def wrapper2(func):
        def inner():
            print('wrapper2 ,before func')
            func()
            print('wrapper2 ,after func')
        return inner
    
    @wrapper2
    @wrapper1
    def f():
        print('in f')
    
    f()
    多个装饰一个函数
  • 相关阅读:
    网络嗅探与协议分析之验收题
    20199121《网络攻防实践》第四周作业
    如何设计一个卡方检验
    20199121《网络攻防实践》第三周作业
    openssl制作证书全过程及https实现
    Padding Oracle攻击解密AES
    virt-sysprep命令清理缓存文件时失败的解决方法
    OpenStack的centos镜像制作
    KVM--Host does not support any virtualization...
    Centos7 安装VNC实现远程桌面
  • 原文地址:https://www.cnblogs.com/while-number/p/9215610.html
Copyright © 2020-2023  润新知