美文网首页
函数装饰器

函数装饰器

作者: 蝉时雨丶 | 来源:发表于2020-05-11 17:22 被阅读0次

    不带参数的装饰器

    >>> import time
    >>> def timer(func):
          def deco():
            start=time.time()
            func()
            stop=time.time()
            print(stop-start)
          return deco
    >>> def test():
        time.sleep(2)
        print("test is running!")
    
    >>> test=timer(test)
    >>> test()
    test is running!
    2.002716302871704
    

    等价于

    >>> import time
    >>> def timer(func):
        def deco():
            start=time.time()
            func()
            stop=time.time()
            print(stop-start)
        return deco
    
    >>> @timer
    def test():
        time.sleep(2)
        print("test is running!")
    >>> test()
    test is running!
    2.025238513946533
    

    对带参数函数进行装饰

    def w_say(fun):
        """
        如果原函数有参数,那闭包函数必须保持参数个数一致,并且将参数传递给原方法
        """
    
        def inner(name):
            """
            如果被装饰的函数有行参,那么闭包函数必须有参数
            :param name:
            :return:
            """
            print('say inner called')
            fun(name)
    
        return inner
    
    @w_say
    def hello(name):
        print('hello ' + name)
    
    
    hello('wangcai')
    

    输出结果为

    say inner called
    hello wangcai
    

    具体说明代码注释已经有了,就不再单独说明了。
    此时,也许你就会问了,那是一个参数的,如果多个或者不定长参数呢,该如何处理呢?看看下面的代码你就秒懂了。

    def w_add(func):
        def inner(*args, **kwargs):
            print('add inner called')
            func(*args, **kwargs)
        return inner
    @w_add
    def add(a, b):
        print('%d + %d = %d' % (a, b, a + b))
    @w_add
    def add2(a, b, c):
        print('%d + %d + %d = %d' % (a, b, c, a + b + c))
    add(2, 4)
    add2(2, 4, 6)
    

    输出结果为:

    add inner called
    2 + 4 = 6
    add inner called
    2 + 4 + 6 = 12
    

    对带有返回值的函数进行装饰

    下面对有返回值的函数进行装饰,按照之前的写法,代码是这样的

    def w_test(func):
        def inner():
            print('w_test inner called start')
            func()
            print('w_test inner called end')
        return inner
    @w_test
    def test():
        print('this is test fun')
        return 'hello'
    ret = test()
    print('ret value is %s' % ret)
    

    输出结果为:

    w_test inner called start
    this is test fun
    w_test inner called end
    ret value is None
    

    可以发现,此时,并没有输出test函数的‘hello’,而是None,那是为什么呢,可以发现,在inner函数中对test进行了调用,但是没有接受不了返回值,也没有进行返回,那么默认就是None了,知道了原因,那么来修改一下代码:

    def w_test(func):
        def inner():
            print('w_test inner called start')
            str = func()
            print('w_test inner called end')
            return str
        return inner
    @w_test
    def test():
        print('this is test fun')
        return 'hello'
    ret = test()
    print('ret value is %s' % ret)
    

    输出结果:

    w_test inner called start
    this is test fun
    w_test inner called end
    ret value is hello
    

    带参数的装饰器

    def func_args(pre='xiaoqiang'):
        def w_test_log(func):
            def inner():
                print('...记录日志...visitor is %s' % pre)
                func()
            return inner
        return w_test_log
    # 带有参数的装饰器能够起到在运行时,有不同的功能
    # 先执行func_args('wangcai'),返回w_test_log函数的引用
    # @w_test_log
    # 使用@w_test_log对test_log进行装饰
    @func_args('wangcai')
    def test_log():
        print('this is test log')
    test_log()
    

    输出结果为:
    ...记录日志...visitor is wangcai
    this is test log

    简单理解,带参数的装饰器就是在原闭包的基础上又加了一层闭包,通过外层函数func_args的返回值w_test_log就看出来了,具体执行流程在注释里已经说明了。
    好处就是可以在运行时,针对不同的参数做不同的应用功能处理。

    相关文章

      网友评论

          本文标题:函数装饰器

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