我刚刚开始学习Python,对于“记忆化”的概念和使用方法一无所知。能否给出一个简单的示例呢?
我刚刚开始学习Python,对于“记忆化”的概念和使用方法一无所知。能否给出一个简单的示例呢?
这个解决方案可同时处理位置参数和关键字参数,而不考虑传递关键字参数的顺序(使用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
functools.lru_cache
。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.cache
和 @functools.lru_cache(maxsize=None)
一样快, 在我的系统上循环一百万次需要0.122秒(15次运行中最佳结果)self.cache
类变量仍然比较慢,在我的系统上循环一百万次需要0.214秒(15次运行中最佳结果)后两者的实现方式与当前得票最高的答案中所描述的类似。
这是没有内存耗尽预防措施的情况下,即我没有在class
或global
方法中添加代码来限制缓存的大小,这真的是最基本的实现。如果您需要,lru_cache
方法可以免费提供此功能。
对我来说一个未解决的问题是如何对具有functools
装饰器的内容进行单元测试。是否有可能以某种方式清空缓存?使用类方法(可以为每个测试实例化一个新类)或次要地使用全局变量方法(因为您可以执行yourimportedmodule.cachevariable = {}
来清空它)似乎是最干净的单元测试。