装饰器

作者: 陆_志东 | 来源:发表于2018-09-02 22:22 被阅读0次

    装饰器的作用是在不改变现有函数的结构上添加新的功能
    比如现在有个函数A

    import time
    
    
    def A():
        for i in range(3):
            time.sleep(0.2)
            print(i, end=" ")
    
    
    A()
    >> 0 1 2 
    

    现在我们想要在不改变函数A的前提下想要知道程序运行一次需要多久的时间,使用装饰器

    import time
    import functools
    
    
    def detection_runtime(func):
        @functools.wraps(func)
        def detection(*args,**kwargs): # 原函数也就是func接收的参数会被传递到这里
            start = time.clock()
            result = func(*args,**kwargs)
            end = time.clock()
            print("runtime is {}".format(end-start))
            return result
        return detection
    

    上面的装饰器已经写好,下面调用装饰器,有两种方式

    方式一:使用@方式

    import time
    import functools
    
    
    def detection_runtime(func):
        @functools.wraps(func)
        def detection(*args,**kwargs):
            start = time.clock()
            result = func(*args,**kwargs)
            end = time.clock()
            print("runtime is {}".format(end-start))
            return result
        return detection
    
    
    @detection_runtime
    def A():
        for i in range(3):
            time.sleep(0.2)
            print(i, end=" ")
    
    
    A()
    >> 0 1 2 runtime is 0.5995562511980463
    

    方式二:像函数一样调用

    import time
    import functools
    
    
    def detection_runtime(func):
        @functools.wraps(func)
        def detection(*args,**kwargs):
            start = time.clock()
            result = func(*args,**kwargs)
            end = time.clock()
            print("runtime is {}".format(end-start))
            return result
        return detection
    
    
    def A():
        for i in range(3):
            time.sleep(0.2)
            print(i, end=" ")
    
    
    A = detection_runtime(A)  # 这种方式在你无法修改源代码的时候比较适合使用
    A()
    >> 0 1 2 runtime is 0.5998113312916864
    

    魔法方法__name__可以打印函数的名字

    多个装饰器共同装饰一个函数的情况

    当有多个装饰器装饰同一个函数的时候,离函数近的装饰器优先执行

    from functools import wraps
    
    
    def decoratort1(func):
        @wraps(func)
        def decorator(*args,**kwargs):
            return "<b>" + func(*args,**kwargs) + "</b>"
        return decorator
    
    
    def decoratort2(func):
        @wraps(func)
        def decorator(*args,**kwargs):
            return "<i>" + func(*args,**kwargs) + "</i>"
        return decorator
    
    
    @decoratort1
    @decoratort2
    def test(): # decoratort2 会优先装饰
        return "hello world"
    
    
    print(test())
    >> <b><i>hello world</i></b>
    

    三层装饰器

    如果装饰器需要传参就需要三层装饰器了,框架的路由其实就是使用的三层装饰器

    from functools import wraps
    
    
    def decoratort_outer(arg1=None):
        print("received arg : {}".format(arg1))
        def decoratort_middle(func):
            @wraps(func)
            def decorator(*args,**kwargs):
                return "<b>" + func(*args,**kwargs) + "</b>"
            return decorator
        return decoratort_middle
    
    
    @decoratort_outer("hello python")
    def test():
        return "hello world"
    
    
    print(test())
    >> received arg : hello python
    >> <b>hello world</b>
    

    同时支持两层和三层的通用装饰器

    from functools import wraps
    
    
    def decoratort_outer(func):
        if callable(func):
            @wraps(func)
            def decorator(*args, **kwargs):
                return "<b>" + func(*args, **kwargs) + "</b>"
    
            return decorator
        else:
            print("received arg : {}".format(func)) # 注意这个func是装饰器传递的参数
            def decoratort_middle(func):  # 这个func是被装饰的函数
                @wraps(func)
                def decorator(*args,**kwargs):
                    return "<b>" + func(*args,**kwargs) + "</b>"
                return decorator
            return decoratort_middle
    
    
    @decoratort_outer("hello python")
    def test():
        return "hello world"
    
    
    @decoratort_outer
    def test1():
        return "haha"
    
    
    print(test())
    >> received arg : hello python
    >> <b>hello world</b>
    
    print(test1())
    >> <b>haha</b>
    

    相关文章

      网友评论

        本文标题:装饰器

        本文链接:https://www.haomeiwen.com/subject/hqujwftx.html