我刚开始学习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]
其他回答
记忆是将函数转换为数据结构的过程。通常,人们希望增量地、惰性地进行转换(根据给定的域元素——或“键”的要求)。在惰性函数语言中,这种惰性转换可以自动发生,因此可以在没有(显式)副作用的情况下实现内存化。
记忆基本上是保存用递归算法完成的过去操作的结果,以便在以后需要进行相同的计算时减少遍历递归树的需要。
参见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]
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]
不要忘记内置的hasattr函数,对于那些想要手工制作的人来说。这样就可以将mem缓存保存在函数定义中(而不是全局缓存)。
def fact(n):
if not hasattr(fact, 'mem'):
fact.mem = {1: 1}
if not n in fact.mem:
fact.mem[n] = n * fact(n - 1)
return fact.mem[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类稍微健壮一些。
推荐文章
- 使用python创建一个简单的XML文件
- APT命令行界面式的yes/no输入?
- 如何打印出状态栏和百分比?
- 在Python中获取大文件的MD5哈希值
- 在Python格式字符串中%s是什么意思?
- 如何循环通过所有但最后一项的列表?
- python用什么方法避免默认参数为空列表?
- ValueError: numpy。Ndarray大小改变,可能表示二进制不兼容。期望从C头得到88,从PyObject得到80
- Anaconda /conda -安装特定的软件包版本
- 我在哪里调用Keras的BatchNormalization函数?
- 打印测试执行时间并使用py.test锁定缓慢的测试
- 插入一行到熊猫数据框架
- 要列出Pandas DataFrame列
- 在Django模型中存储电话号码的最佳方法是什么?
- 从导入的模块中模拟函数