Memoization装饰器比原始函数

时间:2017-08-23 22:00:28

标签: python decorator

我正在做具有斐波那契功能的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

1 个答案:

答案 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 = {}返回之前,该行应该超出该功能。