我刚开始使用Python, 却不知道什么是记忆以及如何使用它。 另外,我能够举一个简化的例子吗? html
备注基本上是保存使用递归算法完成的过去操做的结果,以减小在之后须要相同计算时遍历递归树的需求。 python
参见http://scriptbucket.wordpress.com/2012/12/11/introduction-to-memoization/ 算法
Python中的斐波那契记忆示例: 缓存
fibcache = {} def fib(num): if num in fibcache: return fibcache[num] else: fibcache[num] = num if num < 2 else fib(num-1) + fib(num-2) return fibcache[num]
cache = {} def fib(n): if n <= 1: return n else: if n not in cache: cache[n] = fib(n-1) + fib(n-2) return cache[n]
Python 3.2的新功能是functools.lru_cache
。 默认状况下,它仅缓存最近使用的128个调用,可是您能够将maxsize
设置为None
以指示缓存永不过时: ide
import functools @functools.lru_cache(maxsize=None) def fib(num): if num < 2: return num else: return fib(num-1) + fib(num-2)
此功能自己很是慢,尝试使用fib(36)
,您将不得不等待大约十秒钟。 wordpress
添加lru_cache
注释可确保若是最近已为特定值调用了该函数,则不会从新计算该值,而是使用已缓存的先前结果。 在这种状况下,它能够极大地提升速度,而代码不会因缓存的细节而混乱。 函数
这是一个能够解决列表或字典类型参数而无需抱怨的解决方案: spa
def memoize(fn): """returns a memoized version of any function that can be called with the same list of arguments. Usage: foo = memoize(foo)""" def handle_item(x): if isinstance(x, dict): return make_tuple(sorted(x.items())) elif hasattr(x, '__iter__'): return make_tuple(x) else: return x def make_tuple(L): return tuple(handle_item(x) for x in L) def foo(*args, **kwargs): items_cache = make_tuple(sorted(kwargs.items())) args_cache = make_tuple(args) if (args_cache, items_cache) not in foo.past_calls: foo.past_calls[(args_cache, items_cache)] = fn(*args,**kwargs) return foo.past_calls[(args_cache, items_cache)] foo.past_calls = {} foo.__name__ = 'memoized_' + fn.__name__ return foo
请注意,经过在handle_item中做为特殊状况实现本身的哈希函数,能够天然地将此方法扩展到任何对象。 例如,要使此方法适用于将集合做为输入参数的函数,能够将其添加到handle_item中: code
if is_instance(x, set): return make_tuple(sorted(list(x)))
记忆有效地指基于方法输入记忆方法调用的结果(“记忆”→“备忘录”→要记忆),而后返回记忆的结果,而不是再次计算结果。 您能够将其视为方法结果的缓存。 有关更多详细信息,请参见第387页的Cormen等人的算法简介 (3e)中的定义。 orm
一个简单的示例,使用Python中的记忆来计算阶乘是这样的:
factorial_memo = {} def factorial(k): if k < 2: return 1 if k not in factorial_memo: factorial_memo[k] = k * factorial(k-1) return factorial_memo[k]
您可能会变得更加复杂,并将备注过程封装到一个类中:
class Memoize: def __init__(self, f): self.f = f self.memo = {} def __call__(self, *args): if not args in self.memo: self.memo[args] = self.f(*args) #Warning: You may wish to do a deepcopy here if returning objects return self.memo[args]
而后:
def factorial(k): if k < 2: return 1 return k * factorial(k - 1) factorial = Memoize(factorial)
Python 2.4中添加了一个称为“ 装饰器 ”的功能,使您如今只需编写如下代码便可完成相同的操做:
@Memoize def factorial(k): if k < 2: return 1 return k * factorial(k - 1)
Python Decorator库有一个相似的装饰器,称为memoized
,它比此处显示的Memoize
类更健壮。