在 python 中缓存函数的最后 k 个结果
caching last k results of a function in python
我想编写一个接受单参数函数 f 和整数 k 的函数,以及 returns 一个行为与 f 相同的函数,除了它缓存 f 的最后 k 个结果。
例如,如果 memoize 是我们之后的函数,让 mem_f = memoize(f, 2),那么:
mem_f(arg1) -> f(arg1) is computed and cached
mem_f(arg1) -> f(arg1) is returned from cache
mem_f(arg2) -> f(arg2) is computed and cached
mem_f(arg3) -> f(arg3) is computed and cached, and f(arg1) is evicted
我所做的是:
def memoize(f,k):
cache = dict()
def mem_f(*args):
if args in cache:
return cache[args]
result = f(*args)
cache[args]= result
return result
return mem_f
此函数returns 缓存中的结果,如果不在缓存中,则计算并缓存。但是,我不清楚 如何只缓存 f 的最后 k 个结果? 我是新手,如有任何帮助,我们将不胜感激。
解决方案
您可以像这样使用 OrderedDict
修复您拥有的代码:
from collections import OrderedDict
def memoize(f, k):
cache = OrderedDict()
def mem_f(*args):
if args in cache:
return cache[args]
result = f(*args)
if len(cache) >= k:
cache.popitem(last=False)
cache[args]= result
return result
return mem_f,cache
正在测试
def mysum(a, b):
return a + b
mysum_cached,cache = memoize(mysum, 10)
for i in range(100)
mysum_cached(i, i)
print(cache)
输出:
OrderedDict([((90, 90), 180), ((91, 91), 182), ((92, 92), 184), ((93, 93), 186), ((94, 94), 188), ((95, 95), 190), ((96, 96), 192), ((97, 97), 194), ((98, 98), 196), ((99, 99), 198)])
此版本的 memoize
可能适用于您自己的代码。但是,对于生产代码(即其他人必须依赖的代码),您可能应该使用 Mark Meyer 建议的标准库函数 (functools.lru_cache
)。
您可以只使用 functools.lru_cache
进行缓存。我接受一个 maxsize
参数来控制缓存的数量:
from functools import lru_cache
@lru_cache(maxsize=2)
def test(n):
print("calling function")
return n * 2
print(test(2))
print(test(2))
print(test(3))
print(test(3))
print(test(4))
print(test(4))
print(test(2))
结果:
calling function
4
4
calling function
6
6
calling function
8
8
calling function
4
根据 Mark Meyer 的出色建议,下面是使用 lru_cache
和您的问题术语的解决方案:
from functools import lru_cache
def memoize(f, k):
mem_f = lru_cache(maxsize=k)(f)
return mem_f
def multiply(a, b):
print("Called with {}, {}".format(a, b))
return a * b
def main():
memo_multiply = memoize(multiply, 2)
print("Answer: {}".format(memo_multiply(3, 4)))
print("Answer: {}".format(memo_multiply(3, 4)))
print("Answer: {}".format(memo_multiply(3, 7)))
print("Answer: {}".format(memo_multiply(3, 8)))
if __name__ == "__main__":
main()
结果:
Called with 3, 4
Answer: 12
Answer: 12
Called with 3, 7
Answer: 21
Called with 3, 8
Answer: 24
我想编写一个接受单参数函数 f 和整数 k 的函数,以及 returns 一个行为与 f 相同的函数,除了它缓存 f 的最后 k 个结果。
例如,如果 memoize 是我们之后的函数,让 mem_f = memoize(f, 2),那么:
mem_f(arg1) -> f(arg1) is computed and cached
mem_f(arg1) -> f(arg1) is returned from cache
mem_f(arg2) -> f(arg2) is computed and cached
mem_f(arg3) -> f(arg3) is computed and cached, and f(arg1) is evicted
我所做的是:
def memoize(f,k):
cache = dict()
def mem_f(*args):
if args in cache:
return cache[args]
result = f(*args)
cache[args]= result
return result
return mem_f
此函数returns 缓存中的结果,如果不在缓存中,则计算并缓存。但是,我不清楚 如何只缓存 f 的最后 k 个结果? 我是新手,如有任何帮助,我们将不胜感激。
解决方案
您可以像这样使用 OrderedDict
修复您拥有的代码:
from collections import OrderedDict
def memoize(f, k):
cache = OrderedDict()
def mem_f(*args):
if args in cache:
return cache[args]
result = f(*args)
if len(cache) >= k:
cache.popitem(last=False)
cache[args]= result
return result
return mem_f,cache
正在测试
def mysum(a, b):
return a + b
mysum_cached,cache = memoize(mysum, 10)
for i in range(100)
mysum_cached(i, i)
print(cache)
输出:
OrderedDict([((90, 90), 180), ((91, 91), 182), ((92, 92), 184), ((93, 93), 186), ((94, 94), 188), ((95, 95), 190), ((96, 96), 192), ((97, 97), 194), ((98, 98), 196), ((99, 99), 198)])
此版本的 memoize
可能适用于您自己的代码。但是,对于生产代码(即其他人必须依赖的代码),您可能应该使用 Mark Meyer 建议的标准库函数 (functools.lru_cache
)。
您可以只使用 functools.lru_cache
进行缓存。我接受一个 maxsize
参数来控制缓存的数量:
from functools import lru_cache
@lru_cache(maxsize=2)
def test(n):
print("calling function")
return n * 2
print(test(2))
print(test(2))
print(test(3))
print(test(3))
print(test(4))
print(test(4))
print(test(2))
结果:
calling function
4
4
calling function
6
6
calling function
8
8
calling function
4
根据 Mark Meyer 的出色建议,下面是使用 lru_cache
和您的问题术语的解决方案:
from functools import lru_cache
def memoize(f, k):
mem_f = lru_cache(maxsize=k)(f)
return mem_f
def multiply(a, b):
print("Called with {}, {}".format(a, b))
return a * b
def main():
memo_multiply = memoize(multiply, 2)
print("Answer: {}".format(memo_multiply(3, 4)))
print("Answer: {}".format(memo_multiply(3, 4)))
print("Answer: {}".format(memo_multiply(3, 7)))
print("Answer: {}".format(memo_multiply(3, 8)))
if __name__ == "__main__":
main()
结果:
Called with 3, 4
Answer: 12
Answer: 12
Called with 3, 7
Answer: 21
Called with 3, 8
Answer: 24