函数装饰器

Jai*_*ime 6 python decorator argument-passing

我喜欢能够测量我编码的python函数的性能,所以我经常做类似的事情......

import time

def some_function(arg1, arg2, ..., argN, verbose = True) :
    t = time.clock() # works best in Windows
    # t = time.time() # apparently works better in Linux

    # Function code goes here

    t = time.clock() - t
    if verbose :
        print "some_function executed in",t,"sec."

    return return_val
Run Code Online (Sandbox Code Playgroud)

是的,我知道你应该用timeit测量性能,但这对我的需求来说很好,并且允许我打开和关闭这些信息以便非常顺利地进行调试.

那段代码当然是在我了解函数装饰器之前...不是我现在对它们了解很多,但我想我可以使用**kwds字典编写一个装饰器来执行以下操作:

some_function(arg1, arg2, ..., argN) # Does not time function
some_function(arg1, arg2, ..., argN, verbose = True) # Times function
Run Code Online (Sandbox Code Playgroud)

不过,我想复制我的函数的先前工作,以便工作更像是:

some_function(arg1, arg2, ..., argN) # Does not time function
some_function(arg1, arg2, ..., argN, False) # Does not time function
some_function(arg1, arg2, ..., argN, True) # Times function
Run Code Online (Sandbox Code Playgroud)

我想这需要装饰器计算参数的数量,知道原始函数需要多少,去掉任何多余的,将它们的正确数量传递给函数...我不知道如何告诉python做到这一点......有可能吗?有没有更好的方法来实现同样的目标?

Ste*_*202 9

虽然检查可以让你在路上了一下,你想要的是在一般没有可能的:

def f(*args):
    pass
Run Code Online (Sandbox Code Playgroud)

现在需要多少参数f?由于*args**kwargs允许任意数量的参数,因此无法确定函数所需的参数数量.事实上,有些情况下,函数真正处理的次数与抛出的次数一样多!


编辑:如果您愿意忍受verbose作为特殊关键字参数,您可以这样做:

import time

def timed(f):
    def dec(*args, **kwargs):
        verbose = kwargs.pop('verbose', False)
        t = time.clock()

        ret = f(*args, **kwargs)

        if verbose:
            print("%s executed in %ds" % (f.__name__, time.clock() - t))

        return ret

    return dec

@timed
def add(a, b):
    return a + b

print(add(2, 2, verbose=True))
Run Code Online (Sandbox Code Playgroud)

(感谢亚历马尔泰利kwargs.pop提示!)


Ale*_*lli 8

然而,在Stephan202的答案上+1(将其放在一个单独的答案中,因为评论不能很好地格式化代码!),该答案中的以下代码:

verbose = False
if 'verbose' in kwargs:
     verbose = True
     del kwargs['verbose']
Run Code Online (Sandbox Code Playgroud)

可以更清晰,更简洁地表达为:

verbose = kwargs.pop('verbose', False)
Run Code Online (Sandbox Code Playgroud)