functools.wraps: update_wrapper的封装

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等等,让使用者很方便就能使用框架,本质上也避免了重复代码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 装饰是为函数和类指定管理代码的一种方式.装饰器本身的形式是处理其他的可调用对象的可调用的对象。 函数装饰器在函数定...
    低吟浅唱1990阅读 1,688评论 0 0
  • Python装饰器的高级用法(翻译) 原文地址https://www.codementor.io/python/t...
    城南道阅读 10,231评论 1 22
  • 这两天学习的时候对python中的闭包产生了兴趣,网上这篇文章写得很好,写在这里大家看看。 1. 闭包的概念 首...
    Alistair阅读 1,837评论 0 0
  • 回到本心,回到过去,过去在美化的滤镜中呈现出镜花水月的模糊轮廓,你不甘心,伸手狠狠地抓去,自然无所得——所谓的“过...
    王大可Rukia阅读 5,737评论 7 18
  • 他和孩子在那 我在这 这就是最好的时光
    仉婧阅读 1,468评论 0 0

友情链接更多精彩内容