美文网首页
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的

    This is a convenience function for invoking partial(updat...

  • python中的闭包和装饰器

    functools.wraps用法 """2.装饰器wraps解释functools.wraps 是 装饰器的装饰...

  • python 的funtools模块

    functools.partial functools.update_wrapper functools.wraps

  • Python装饰器20-update_wrapper

    使用update_wrapper改变装饰后函数的属性 Python还提供定制化更强的函数update_wrappe...

  • functools模块

    一.update_wrapper 该函数用于更新包装函数(wrapper),使它看起来像被包装的原函数一样。该函数...

  • Python中的装饰器

    Python中的装饰器 不带参数的装饰器 带参数的装饰器 类装饰器 functools.wraps 使用装饰器极大...

  • py装饰器二

    functools.wraps是个很 hack 的方法,它本事作为一个装饰器,做用在装饰器内部将要返回的函数上。也...

  • Python面试基础(二)

    1. 装饰器之functools.wraps 装饰器很好用极大地复用了代码,但是不可否认在给原函数使用装饰器后原函...

  • 的的的

    来看看我

  • 的的

    妹妹从小学说话的时候就喊哥哥叫的的哥哥偶尔还会去纠正一下,“不叫的的叫哥哥”但是后来也懒得纠正了。 妹妹最爱吃肉,...

网友评论

      本文标题:functools.wraps: update_wrapper的

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