这是我的代码。
import timeit
fac_mem = {}
def fac(k):
if k < 2: return 1
if k not in fac_mem:
fac_mem[k] = k*fac(k-1)
return fac_mem[k]
def fact(k):
if k < 2: return 1
return k*fact(k-1)
if __name__ == "__main__":
print timeit.timeit("fac(7)","from __main__ import fac")
print timeit.timeit("fact(7)","from __main__ import fact")
print timeit.timeit("fac(70)","from __main__ import fac")
print timeit.timeit("fact(70)","from __main__ import fact")
这是输出
0.236774399224
0.897065011572
0.217623144304
14.1952226578
好吧,在程序运行之前,dict是空的,为什么memoization仍然加速了阶乘?我的意思是,这两个版本的调用次数是相同的。 然后我稍微更改了代码,将dict移动到函数中。
def fac(k):
fac_mem = {}
if k < 2: return 1
if k not in fac_mem:
fac_mem[k] = k*fac(k-1)
return fac_mem[k]
输出已更改
1.92900857225
0.910026658388
25.5475004875
14.2164999769
为什么慢?那是因为函数内部生成的值暂时存储在堆栈中吗?变量外部是全球性的,但是什么使它变得如此之快? 请有人帮我清理一下吗?我很感激。
答案 0 :(得分:4)
当您运行timeit.timeit
而未指定关键字number
的参数时,它会执行您传递1000000次的代码。如果在Python的全局范围内保留一个名为fac_mem
的全局字典,它将保存该字典中第一次执行的结果。
因此,您的memoized factorial函数在第一次执行时只会很慢,而实际上它必须进行计算。剩下的999999次它只会在字典中查找答案并避免进行计算。
如果你将字典保留在函数内部,那么每次Python将函数放在函数内时它都会被销毁(因为当函数返回时,对字典的所有引用都将被销毁)。因此,字典将无法保存其答案,并且对于将来的执行仍然会保持缓慢。
答案 1 :(得分:3)
这意味着1个正常速度呼叫和99个超快速呼叫被平均在一起。这使得memoized函数看起来更快。
如果要测量实际速度,则需要在每次测试调用后清除memoization字典。