我有一个我写的装饰器,它将为给定的函数计时。它似乎适用于任何函数,除了递归函数。
装饰:
def tictoc(repeats=3, loops=1):
def t(func):
from functools import partial, wraps
import timeit
@wraps(func)
def timer(*args, **kargs):
elapsed = timeit.repeat(partial(func, *args, **kargs), repeat = repeats, number=loops)
mine = min(elapsed)
print "%s finished in %.5fs (%d loops, %d times) with %.5fs per loop" % (func.__name__, mine, loops, repeats, mine/loops)
return timer
return t
递归函数是基本的Fibonacci算法。
@tictoc()
def fib(i):
return ( 0 if i == 0 else
1 if i == 1 else
fib(i-1) + fib(i-2) )
fib(15)
程序失败,出现以下错误
fib finished in 0.00000s (1 loops, 3 times) with 0.00000s per loop
fib finished in 0.00000s (1 loops, 3 times) with 0.00000s per loop
fib finished in 0.00000s (1 loops, 3 times) with 0.00000s per loop
Traceback (most recent call last):
File "decor.py", line 61, in <module>
[fib(x) for x in range(1,50)]
File "/home/grout/Dropbox/Python/tictoc.py", line 7, in timer
elapsed = timeit.repeat(partial(func, *args, **kargs), repeat = repeats, number=loops)
File "/usr/lib/python2.7/timeit.py", line 233, in repeat
return Timer(stmt, setup, timer).repeat(repeat, number)
File "/usr/lib/python2.7/timeit.py", line 221, in repeat
t = self.timeit(number)
File "/usr/lib/python2.7/timeit.py", line 194, in timeit
timing = self.inner(it, self.timer)
File "/usr/lib/python2.7/timeit.py", line 100, in inner
_func()
File "decor.py", line 59, in fib
fib(i-1) + fib(i-2) )
TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'
我不明白的是装饰器如何执行几次然后失败。任何帮助将不胜感激。
答案 0 :(得分:6)
装饰器返回的函数不返回任何内容。因此,虽然fib
应该返回一个整数,但是包裹的fib
会返回None
。它工作了几次,因为在没有检查fib
的结果的情况下进行了一些递归调用,但是当它需要结果时(当它必须将它们中的两个一起添加时),你得到了异常。
答案 1 :(得分:0)
我想我会解决这个问题
def tictoc(func, repeats=3, loops=100, *args, **kargs):
elapsed = timeit.repeat(lambda: func(*args, **kargs), repeat = repeats, number = loops)
mine = min(elapsed)
return "%s finished in %.5fs (%s loops, repeated %s times): %.5fs best time per loop" %(func.__name__, mine, loops, repeats, mine/loops)