什麼是備忘錄,如何在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類更健壯。

相關文章
相關標籤/搜索