zoukankan      html  css  js  c++  java
  • python基础篇_004_装饰器函数

    python装饰器函数

    1.装饰器函数引导

    功能:计算函数执行时长

    import time
    
    """
    方式一:
    函数首位添加时间,差值就是函数执行时间
    缺点:每个函数都要加上,工作量大
    """
    def f1():
        start_time = time.time()
        print("f1 excute")
        end_time = time.time()
        print(end_time-start_time)
    
    f1()
    import time
    
    """
    方式二:
    调用函数前后
    缺点:调用函数前后都要加,别人引用的也要加
    """
    
    
    def f1():
        print("f1 excute")
    
    
    start_time = time.time()
    f1()
    end_time = time.time()
    print(end_time - start_time)
    import time
    
    """
    方式三:
    写个计算函数执行时间函数
    缺点:改变了函数的调用方式
    """
    
    
    def f1():
        print("f1 excute")
    
    
    def timer(func):
        start_time = time.time()
        func
        end_time = time.time()
        print(end_time - start_time)
    
    
    timer(f1())

    想要不改变调用方式的前提下完成该功能

    import time
    
    """
    方式四:
    缺点:还要复制操作
    """
    
    
    def f1():
        print("f1 excute")
    
    
    def timer(func):
        def inner():
            start_time = time.time()
            func
            end_time = time.time()
            print(end_time - start_time)
        return inner
    
    f1 = timer(f1())
    f1()

    直接将赋值操作替换

    import time
    
    def timer(func):
        def inner():
            start_time = time.time()
            func()
            end_time = time.time()
            print(end_time - start_time)
    
        return inner
    
    
    @timer
    def f1():
        print("f1 excute")
    
    f1()
    总结:
    装饰器的本质:一个闭包函数
    装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展
    #带参数
    import time def timer(func): def inner(a): start
    = time.time() func(a) print(time.time() - start) return inner @timer def f1(a): print(a) f1(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'))
    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 f1(a, b):
        print('f1 excute ,a=%s,b=%s' % (a, b))
    
    
    @timer  # ==> func2 = timer(func2)
    def f2(a):
        print(a)
        return 'f2 over'
    
    
    f1('x1', 'x2')
    a = f2('a')
    print(a)
    # f1 excute ,a=x1,b=x2
    # 0.0
    # a
    # 0.0
    # f2 over
    import time
    # from functools import wraps
    
    
    def timer(func):
        # @wraps(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 f1(a, b):
        """f1函数注释"""
        print('f1 excute ,a=%s,b=%s' % (a, b))
    
    
    @timer  # ==> func2 = timer(func2)
    def f2(a):
        """f2函数注释"""
        print(a)
        return 'f2 over'
    
    
    print(f1.__doc__)  # 查看函数注释  None
    print(f1.__name__) # 查看函数名称  inner

    正常情况:

    def demo():
        """函数注释"""
        print("a")
    
    
    print(demo.__doc__)  # 查看函数注释    函数注释
    print(demo.__name__)  # 查看函数名称   demo

    为防止失效:

    import time
    from functools import wraps
    
    
    def timer(func):
        @wraps(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 f1(a, b):
        """f1函数注释"""
        print('f1 excute ,a=%s,b=%s' % (a, b))
    
    
    @timer  # ==> func2 = timer(func2)
    def f2(a):
        """f2函数注释"""
        print(a)
        return 'f2 over'
    
    
    print(f1.__doc__)  # 查看函数注释  f1函数注释
    print(f1.__name__) # 查看函数名称  f1

    2.开放封闭原则

    1.对扩展是开放的
    我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
    
    2.对修改是封闭的
    就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。

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

    3.装饰器的主要功能和装饰器的固定结构

    装饰器的主要功能:在不修改原函数的调用方式的基础上,在函数前后添加功能,实现功能扩展

    from functools import wraps
    
    
    def demo(func):
        @wraps(func)  # 防止查看函数注释等方法失效
        def inner(*args, **kwargs):
            """调用函数前要实现的功能"""
            re = func(*args, **kwargs)
            """调用函数后要实现的功能"""
            return re
    
        return inner

    4.带参数的装饰器

    使用参数控制装饰器的使用与否:在后面再嵌套一层

    from functools import wraps
    
    
    def outer(flag):
        def demo(func):
            @wraps(func)
            def inner(*args, **kwargs):
                if flag: print("函数调用前")
                re = func(*args, **kwargs)
                if flag: print("函数调用后")
                return re
    
            return inner
    
        return demo
    
    
    @outer(False)
    def f1():
        print("f1 execute")
    
    f1()

    多个装饰器装饰同一个函数

    from functools import wraps
    
    
    def timer1(func):
        @wraps(func)
        def inner(*args, **kwargs):
            print('''timer1执行函数之前要做的''')
            re = func(*args, **kwargs)
            print('''timer1执行函数之后要做的''')
            return re
    
        return inner
    
    
    def timer2(func):
        @wraps(func)
        def inner(*args, **kwargs):
            print('''timer2执行函数之前要做的''')
            re = func(*args, **kwargs)
            print('''timer2执行函数之后要做的''')
            return re
    
        return inner
    
    
    @timer1
    @timer2
    def func():
        print(111)
    
    
    func()
    # timer1执行函数之前要做的
    # timer2执行函数之前要做的
    # 111
    # timer2执行函数之后要做的
    # timer1执行函数之后要做的
  • 相关阅读:
    微信小程序发送模板消息
    Swoole-WebSocket服务端主动推送消息
    git 批量删除分支
    RdKafka使用
    Kakfa安装,PHP安装RdKafka扩展
    Zookeeper安装、启动、启动失败原因
    Hyperf-事件机制+异常处理
    Hyperf-JsonRpc使用
    hyperf-环境搭建
    CGI、FastCGI、PHPFPM
  • 原文地址:https://www.cnblogs.com/yin-fei/p/10762323.html
Copyright © 2011-2022 走看看