我刚开始学习Python,我不知道什么是内存化,也不知道如何使用它。另外,我可以举一个简单的例子吗?
当前回答
其他答案很好地涵盖了它的本质。我不是在重复。只是一些可能对你有用的观点。
通常,memoisation是一种可以应用在任何函数上的操作,该函数计算一些东西(昂贵的)并返回一个值。因此,它通常被实现为一个装饰器。实现很简单,大概是这样的
memoised_function = memoise(actual_function)
或者表示为装饰者
@memoise
def actual_function(arg1, arg2):
#body
其他回答
如果要考虑速度:
@functools。cache和@functools.lru_cache(maxsize=None)同样快,在我的系统上循环一百万次需要0.122秒(最好运行15次) 全局缓存变量要慢得多,在我的系统上循环一百万次需要0.180秒(最好运行15次) 一个自我。缓存类变量仍然有点慢,在我的系统上循环一百万次需要0.214秒(最好运行15次)
后两者的实现方式与目前投票最多的答案中描述的类似。
这没有防止内存耗尽,也就是说,我没有在类或全局方法中添加代码来限制缓存的大小,这真的是最基本的实现。如果需要的话,lru_cache方法可以免费提供。
对我来说,一个悬而未决的问题是如何对具有functools装饰器的东西进行单元测试。是否有可能以某种方式清空缓存?单元测试似乎使用class方法(在这里您可以为每个测试实例化一个新类)或全局变量方法(因为您可以使用您的rimportedmodule)是最干净的。Cachevariable ={}来清空它)。
我应该先回答第一部分:什么是记忆?
这只是一种用记忆换取时间的方法。想想乘法表。
在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]
我发现这非常有用
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)
与传递关键字参数的顺序无关的位置参数和关键字参数的解决方案(使用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]
更完整的描述可以在维基百科关于记忆的条目中找到。
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录