我正在做具有斐波那契功能的memoized装饰练习。当输入变大时,memoized函数应该快得多,因为它返回字典中的结果而不是再次计算结果。
我正在使用timeit.timeit()
来测量memoized on vs off的函数的执行时间。
我得到的结果与我的期望完全相反。没有装饰器的执行运行得更快。
# memorized decorator for fibonacci series
def mem_fib(f):
def wrapper(n):
wrapper.d = {} # create the attr member of THIS wrapper
if n in wrapper.d:
return wrapper.d[n]
wrapper.d[n] = f(n) # save f() return in a dict
return wrapper.d[n]
return wrapper
@mem_fib
def fibonacci(n):
assert n >= 0
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
我在PyCharm python的控制台上运行命令。
@with decorator
>>> print(timeit.timeit('decorators.fibonacci(7)', setup='import decorators'))
19.6940833939
>>> print(timeit.timeit('decorators.fibonacci(10)', setup='import decorators'))
85.7157191166
没有装饰者的
>>> print(timeit.timeit('decorators.fibonacci(7)', setup='import decorators'))
5.10131571594
>>> print(timeit.timeit('decorators.fibonacci(10)', setup='import decorators'))
21.9784012801
我多次运行timeit,我只输了一个输出来总结它。我错过了什么?
由于
更新:感谢Daniel的回答,我发现了自己的错误。我把字典创建移到了包装器之外,结果好多了。
>>> print(timeit.timeit('decorators.fibonacci(10)', setup='import decorators'))
0.248986574759
答案 0 :(得分:5)
每次调用函数时都会创建一个新字典,因为 <plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<id>default</id>
<goals>
<goal>integration-test</goal>
</goals>
<phase>integration-test</phase>
<configuration>
<failIfNoTests>true</failIfNoTests>
</configuration>
</execution>
<execution>
<id>verify</id>
<phase>verify</phase>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<dependenciesToScan>
<dependency>${project.groupId}:cms-it</dependency>
</dependenciesToScan>
</configuration>
</plugin>
函数始终wrapper
。因此,永远不会填充缓存,并且您的代码每次都会创建字典的额外开销。
在从wrapper.d = {}
返回之前,该行应该超出该功能。