我有一个简单的decorator来跟踪函数调用的运行时:
def timed(f):
def caller(*args):
start = time.time()
res = f(*args)
end = time.time()
return res, end - start
return caller
这可以如下使用,并返回函数结果和执行时间的元组。在
^{pr2}$很简单。但现在我想把它应用到递归函数中。如预期的那样,将上述包装器应用于递归函数将生成嵌套元组,其中包含每次递归调用的次数。在
@timed
def rec(n):
if n:
return rec(n - 1)
else:
return 0
print(rec(3)) # Prints ((((0, 1.90e-06), 8.10e-06), 1.28e-05), 1.90e-05)
编写decorator使其能够正确处理递归的优雅方式是什么?显然,如果定时函数:
@timed
def wrapper():
return rec(3)
这将给出结果和时间的元组,但我希望所有这些都由decorator处理,这样调用者就不必为每次调用定义一个新函数而担心。思想?在
你可以用一种不同的方式来构造你的计时器,通过一点滥用}一点。。。在
contextmanager
和{结果:
^{pr2}$如果这被认为是一次糟糕的黑客攻击,我很乐意接受你的批评。在
到目前为止,我更喜欢其他答案(特别是user2357112's answer),但您也可以创建一个基于类的decorator,它可以检测函数是否已被激活,如果激活了,则绕过计时:
(用
(object)
编写的类,因此它与py2k和py3k兼容)。在请注意,要真正正常工作,最外层的调用应该使用}。以下是
^{pr2}$try
和{__call__
的奇幻版本:这里的问题不是真正的装饰师。问题是}成为一个行为不同的函数。没有一种干净的方法可以将其与单个
rec
需要rec
是一个行为方式不同的函数,但是您希望{rec
函数协调起来。在最干净的选择是停止要求
rec
同时是两个东西。不要使用装饰符号,而是将timed(rec)
指定给其他名称:如果不需要两个名称,则需要编写
^{pr2}$rec
,以了解修饰后的rec
将返回的实际值。例如相关问题 更多 >
编程相关推荐