什么是备忘录,如何在Python中使用备忘录?

我刚开始使用Python, 却不知道什么是记忆以及如何使用它。 另外,我能够举一个简化的例子吗? html


#1楼

备注基本上是保存使用递归算法完成的过去操做的结果,以减小在之后须要相同计算时遍历递归树的需求。 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]

#2楼

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]

#3楼

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注释可确保若是最近已为特定值调用了该函数,则不会从新计算该值,而是使用已缓存的先前结果。 在这种状况下,它能够极大地提升速度,而代码不会因缓存的细节而混乱。 函数


#4楼

这是一个能够解决列表或字典类型参数而无需抱怨的解决方案: 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)))

#5楼

记忆有效地指基于方法输入记忆方法调用的结果(“记忆”→“备忘录”→要记忆),而后返回记忆的结果,而不是再次计算结果。 您能够将其视为方法结果的缓存。 有关更多详细信息,请参见第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类更健壮。

相关文章
相关标签/搜索