我刚开始学习Python,我不知道什么是内存化,也不知道如何使用它。另外,我可以举一个简单的例子吗?


当前回答

我应该先回答第一部分:什么是记忆?

这只是一种用记忆换取时间的方法。想想乘法表。

在Python中使用可变对象作为默认值通常被认为是不好的。但如果明智地使用它,它实际上可以用于实现记忆。

下面是一个摘自http://docs.python.org/2/faq/design.html#why-are-default-values-shared-between-objects的例子

在函数定义中使用可变dict,中间计算结果可以被缓存(例如,在计算阶乘(9)后计算阶乘(10)时,我们可以重用所有中间结果)

def factorial(n, _cache={1:1}):    
    try:            
        return _cache[n]           
    except IndexError:
        _cache[n] = factorial(n-1)*n
        return _cache[n]

其他回答

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]

与传递关键字参数的顺序无关的位置参数和关键字参数的解决方案(使用inspect.getargspec):

import inspect
import functools

def memoize(fn):
    cache = fn.cache = {}
    @functools.wraps(fn)
    def memoizer(*args, **kwargs):
        kwargs.update(dict(zip(inspect.getargspec(fn).args, args)))
        key = tuple(kwargs.get(k, None) for k in inspect.getargspec(fn).args)
        if key not in cache:
            cache[key] = fn(**kwargs)
        return cache[key]
    return memoizer

类似的问题:在Python中识别用于内存化的等效可变参数函数调用

我发现这非常有用

from functools import wraps


def memoize(function):    
    memo = {}
        
    @wraps(function)
    def wrapper(*args):

        # add the new key to dict if it doesn't exist already  
        if args not in memo:
            memo[args] = function(*args)

        return memo[args]

    return wrapper
    
    
@memoize
def fibonacci(n):
    if n < 2: return n
    return fibonacci(n - 1) + fibonacci(n - 2)
    
fibonacci(25)

我应该先回答第一部分:什么是记忆?

这只是一种用记忆换取时间的方法。想想乘法表。

在Python中使用可变对象作为默认值通常被认为是不好的。但如果明智地使用它,它实际上可以用于实现记忆。

下面是一个摘自http://docs.python.org/2/faq/design.html#why-are-default-values-shared-between-objects的例子

在函数定义中使用可变dict,中间计算结果可以被缓存(例如,在计算阶乘(9)后计算阶乘(10)时,我们可以重用所有中间结果)

def factorial(n, _cache={1:1}):    
    try:            
        return _cache[n]           
    except IndexError:
        _cache[n] = factorial(n-1)*n
        return _cache[n]

记忆实际上是指根据方法输入记住(“记忆”→“备忘录”→被记住)方法调用的结果,然后返回记住的结果,而不是重新计算结果。您可以把它看作是方法结果的缓存。更多详细信息,请参阅第387页的算法介绍(3e), Cormen等人的定义。

在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装饰器库有一个类似的装饰器,称为memoized,它比这里显示的Memoize类稍微健壮一些。