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


当前回答

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中使用可变对象作为默认值通常被认为是不好的。但如果明智地使用它,它实际上可以用于实现记忆。

下面是一个摘自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]

与传递关键字参数的顺序无关的位置参数和关键字参数的解决方案(使用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中识别用于内存化的等效可变参数函数调用

记忆是保留昂贵的计算结果并返回缓存的结果,而不是不断地重新计算它。

这里有一个例子:

def doSomeExpensiveCalculation(self, input):
    if input not in self.cache:
        <do expensive calculation>
        self.cache[input] = result
    return self.cache[input]

更完整的描述可以在维基百科关于记忆的条目中找到。

如果要考虑速度:

@functools。cache和@functools.lru_cache(maxsize=None)同样快,在我的系统上循环一百万次需要0.122秒(最好运行15次) 全局缓存变量要慢得多,在我的系统上循环一百万次需要0.180秒(最好运行15次) 一个自我。缓存类变量仍然有点慢,在我的系统上循环一百万次需要0.214秒(最好运行15次)

后两者的实现方式与目前投票最多的答案中描述的类似。

这没有防止内存耗尽,也就是说,我没有在类或全局方法中添加代码来限制缓存的大小,这真的是最基本的实现。如果需要的话,lru_cache方法可以免费提供。

对我来说,一个悬而未决的问题是如何对具有functools装饰器的东西进行单元测试。是否有可能以某种方式清空缓存?单元测试似乎使用class方法(在这里您可以为每个测试实例化一个新类)或全局变量方法(因为您可以使用您的rimportedmodule)是最干净的。Cachevariable ={}来清空它)。

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]