python 中若编写递归函数,为了减少计算时间,需要用到 memoize 或 memoized 功能,它们的作用是记忆函数每次运行的结果,这样当递归函数每次递归时,若已经计算过子函数,就直接从记忆中的结果获取,避免重复计算。
英文解释可以参见:
方法一:使用 memoized 类,代码较多
在使用这个功能时,一般在程序前面加个 memoized 的类(这个类可以直接复制别人写好的代码)就行,然后在定义递归函数时前面加上
@memoized例如斐波那契函数,下面的例子中,没有使用 memoized 功能的计算时间为 41 秒,使用后计算时间为 0秒。
import timeimport functoolsimport collectionsclass memoized(object): '''Decorator. Caches a function's return value each time it is called. If called later with the same arguments, the cached value is returned (not reevaluated). ''' def __init__(self, func): self.func = func self.cache = {} def __call__(self, *args): if not isinstance(args, collections.Hashable): # uncacheable. a list, for instance. # better to not cache than blow up. return self.func(*args) if args in self.cache: return self.cache[args] else: value = self.func(*args) self.cache[args] = value return value def __repr__(self): '''Return the function's docstring.''' return self.func.__doc__ def __get__(self, obj, objtype): '''Support instance methods.''' return functools.partial(self.__call__, obj)def fib(n) : if n in (0, 1): return n return fib(n-1)+fib(n-2)@ memoizeddef fib2(n) : if n in (0, 1): return n return fib2(n-1)+fib2(n-2)start = time.clock()a = fib(40)print(a)end = time.clock()cpu_time = end-startprint('cpu time is %.3f' % cpu_time)start = time.clock()b = fib2(40)print(b)end = time.clock()cpu_time = end-startprint('cpu time after memoizing is %.3f' % cpu_time)
输出结果:
102334155 cpu time is 40.536 102334155 cpu time after memoizing is 0.000方法二:使用 lru_cache(),代码更少
同样需要调用 functools 包,在定义递归函数时前面加上
@lru_cache() 括号里面可以添加数字,表示记忆的条目数量。默认数量是 128。 示例:import timefrom functools import lru_cachedef fib(n) : if n in (0, 1): return n return fib(n-1)+fib(n-2)@lru_cache(1000)def fib3(n) : if n in (0, 1): return n return fib3(n-1)+fib3(n-2)start = time.clock()a = fib(40)print(a)end = time.clock()cpu_time = end-startprint('cpu time is %.3f' % cpu_time)start = time.clock()b = fib3(40)print(b)end = time.clock()cpu_time = end-startprint('cpu time after memoizing is %.3f' % cpu_time)
输出:
102334155 cpu time is 37.304 102334155 cpu time after memoizing is 0.000