开发者社区> 问答> 正文

在函数上添加包装器

你想在函数上添加一个包装器,增加额外的操作处理(比如日志、计时等)。

展开
收起
哦哦喔 2020-04-17 15:34:18 1021 0
2 条回答
写回答
取消 提交回答
  • 有点尴尬唉 你要寻找的东西已经被吃掉啦!
    
    @timethis
    def countdown(n):
        pass
    
    跟像下面这样写其实效果是一样的:
    
    def countdown(n):
        pass
    countdown = timethis(countdown)
    
    顺便说一下,内置的装饰器比如 @staticmethod, @classmethod,@property 原理也是一样的。 例如,下面这两个代码片段是等价的:
    
    class A:
        @classmethod
        def method(cls):
            pass
    
    class B:
        # Equivalent definition of a class method
        def method(cls):
            pass
        method = classmethod(method)
    
    在上面的 wrapper() 函数中, 装饰器内部定义了一个使用 *args 和 **kwargs 来接受任意参数的函数。 在这个函数里面调用了原始函数并将其结果返回,不过你还可以添加其他额外的代码(比如计时)。 然后这个新的函数包装器被作为结果返回来代替原始函数。
    
    需要强调的是装饰器并不会修改原始函数的参数签名以及返回值。 使用 *args 和 **kwargs 目的就是确保任何参数都能适用。 而返回结果值基本都是调用原始函数 func(*args, **kwargs) 的返回结果,其中func就是原始函数。
    
    刚开始学习装饰器的时候,会使用一些简单的例子来说明,比如上面演示的这个。 不过实际场景使用时,还是有一些细节问题要注意的。 比如上面使用 @wraps(func) 注解是很重要的, 它能保留原始函数的元数据(下一小节会讲到),新手经常会忽略这个细节。 接下来的几个小节我们会更加深入的讲解装饰器函数的细节问题,如果你想构造你自己的装饰器函数,需要认真看一下。
    
    2020-04-17 17:47:23
    赞同 展开评论 打赏
  • 如果你想使用额外的代码包装一个函数,可以定义一个装饰器函数,例如:
    
    import time
    from functools import wraps
    
    def timethis(func):
        '''
        Decorator that reports the execution time.
        '''
        @wraps(func)
        def wrapper(*args, **kwargs):
            start = time.time()
            result = func(*args, **kwargs)
            end = time.time()
            print(func.__name__, end-start)
            return result
        return wrapper
    下面是使用装饰器的例子:
    
    >>> @timethis
    ... def countdown(n):
    ...     '''
    ...     Counts down
    ...     '''
    ...     while n > 0:
    ...         n -= 1
    ...
    >>> countdown(100000)
    countdown 0.008917808532714844
    >>> countdown(10000000)
    countdown 0.87188299392912
    >>>
    
    2020-04-17 15:34:42
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
建立联系方法之一 立即下载
继承与功能组合 立即下载
fibjs 模块重构从回调到协程--陈垒 立即下载