我刚开始学习Python,我不知道什么是内存化,也不知道如何使用它。另外,我可以举一个简单的例子吗?
当前回答
记忆是将函数转换为数据结构的过程。通常,人们希望增量地、惰性地进行转换(根据给定的域元素——或“键”的要求)。在惰性函数语言中,这种惰性转换可以自动发生,因此可以在没有(显式)副作用的情况下实现内存化。
其他回答
记忆实际上是指根据方法输入记住(“记忆”→“备忘录”→被记住)方法调用的结果,然后返回记住的结果,而不是重新计算结果。您可以把它看作是方法结果的缓存。更多详细信息,请参阅第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类稍微健壮一些。
记忆是保留昂贵的计算结果并返回缓存的结果,而不是不断地重新计算它。
这里有一个例子:
def doSomeExpensiveCalculation(self, input):
if input not in self.cache:
<do expensive calculation>
self.cache[input] = result
return self.cache[input]
更完整的描述可以在维基百科关于记忆的条目中找到。
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]
functools。缓存装饰:
Python 3.9发布了一个新函数functools.cache。它在内存中缓存带有一组特定参数的函数调用的结果,这就是内存化。它很容易使用:
import functools
import time
@functools.cache
def calculate_double(num):
time.sleep(1) # sleep for 1 second to simulate a slow calculation
return num * 2
第一次调用caculate_double(5)时,它将花费一秒钟并返回10。第二次使用相同的参数calculate_double(5)调用该函数时,它将立即返回10。
添加缓存装饰器可以确保如果函数最近为某个特定值被调用,它将不会重新计算该值,而是使用先前缓存的结果。在这种情况下,它可以极大地提高速度,同时代码不会因为缓存的细节而变得混乱。
(编辑:前面的示例使用递归计算了斐波那契数,但我修改了示例以防止混淆,因此出现了旧的注释。)
functools。lru_cache装饰:
如果您需要支持旧版本的Python,请使用functools。lru_cache适用于Python 3.2+。默认情况下,它只缓存最近使用的128个调用,但你可以将maxsize设置为None来指示缓存永远不会过期:
@functools.lru_cache(maxsize=None)
def calculate_double(num):
# etc
不要忘记内置的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]
推荐文章
- 如何在Flask-SQLAlchemy中按id删除记录
- 在Python中插入列表的第一个位置
- Python Pandas只合并某些列
- 如何在一行中连接两个集而不使用“|”
- 从字符串中移除前缀
- 代码结束时发出警报
- 如何在Python中按字母顺序排序字符串中的字母
- 在matplotlib中将y轴标签添加到次要y轴
- 如何消除数独方块的凹凸缺陷?
- 为什么出现这个UnboundLocalError(闭包)?
- 使用Python请求的异步请求
- 如何检查一个对象是否是python中的生成器对象?
- 如何从Python包内读取(静态)文件?
- 如何计算一个逻辑sigmoid函数在Python?
- python: SyntaxError: EOL扫描字符串文字