美文网首页
functools.wraps: update_wrapper的

functools.wraps: update_wrapper的

作者: williamhyw | 来源:发表于2017-10-07 18:13 被阅读0次

    This is a convenience function for invoking partial(update_wrapper,wrapped=wrapped,assigned=assigned,updated=updated) as a function decorator when defining a wrapper function.

    import functools

    def log_cost_time(func):

        @functools.wraps(func)

        def wrapped(*args, **kwargs):

            import time

            begin = time.time()

            try:

                return func(*args, **kwargs)

            finally:

                print 'func %s cost %s' % (func.__name__, time.time() - begin)

        return wrapped

    再查看complex_func.__name__ 输出就是 “complex_func”

    装饰器也是可以带参数的。

    def log_cost_time(stream):

        def inner_dec(func):

            def wrapped(*args, **kwargs):

                import time

                begin = time.time()

                try:

                    return func(*args, **kwargs)

                finally:

                    stream.write('func %s cost %s ' % (func.__name__, time.time() - begin))

            return wrapped

        return inner_dec

    import sys

    @log_cost_time(sys.stdout)

    def complex_func(num):

        ret = 0

        for i in xrange(num):

            ret += i * i

        return ret

    if __name__ == '__main__':

        print complex_func(100000)

    code snippet 1

    log_cost_time函数也接受一个参数,该参数用来指定信息的输出流,对于带参数的decorator

    @dec(dec_args)

    def func(*args, **kwargs):pass

    等价于 func = dec(dec_args)(*args, **kwargs)。

    装饰器对类的修饰也是很简单的,只不过平时用得不是很多。举个例子,我们需要给修改类的__str__方法,代码很简单。

    def Haha(clz):

        clz.__str__ = lambda s: "Haha"

        return clz

    class Widget(object):

        ''' class Widget '''

    if __name__ == '__main__':

        w = Widget()

        print w

    那什么场景下有必要使用decorator呢,设计模式中有一个模式也叫装饰器。我们先简单回顾一下设计模式中的装饰器模式,简单的一句话概述

    动态地为某个对象增加额外的责任

      由于装饰器模式仅从外部改变组件,因此组件无需对它的装饰有任何了解;

    回到Python中来,用decorator语法实现装饰器模式是很自然的,比如文中的示例代码,在不改变被装饰对象的同时增加了记录函数执行时间的额外功能。当然,由于Python语言的灵活性,decorator是可以修改被装饰的对象的(比如装饰类的例子)。decorator在python中用途非常广泛,下面列举几个方面:

    (1)修改被装饰对象的属性或者行为

    (2)处理被函数对象执行的上下文,比如设置环境变量,加log之类

    (3)处理重复的逻辑,比如有N个函数都可能跑出异常,但是我们不关心这些异常,只要不向调用者传递异常就行了,这个时候可以写一个catchall的decorator,作用于所用可能跑出异常的函数

    def catchall(func):

        @functools.wraps(func)

        def wrapped(*args, **kwargs):

            try:

                return func(*args, **kwargs)

            except:

                pass

        return wrapped

    (4)框架代码,如flask, bottle等等,让使用者很方便就能使用框架,本质上也避免了重复代码。

    相关文章

      网友评论

          本文标题:functools.wraps: update_wrapper的

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