在python中缓存函数的最后k个结果

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在python中缓存函数的最后k个结果相关的知识,希望对你有一定的参考价值。

我想编写一个接受单参数函数f和整数k的函数,并返回一个与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

此函数返回缓存中的结果,如果它不在缓存中,则计算并缓存它。但是,我不清楚如何只缓存f的最后k个结果?我是新手,任何帮助将不胜感激。

答案

你可以使用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))

结果:

调用功能 4 4 调用功能 6 6 调用功能 8 8 调用功能 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
另一答案

Solution

您可以像这样使用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

Testing it out

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)。

以上是关于在python中缓存函数的最后k个结果的主要内容,如果未能解决你的问题,请参考以下文章

13 个非常有用的 Python 代码片段

[python]缓存函数结果进redis

为啥此代码片段返回意外结果?

在 Python 多处理进程中运行较慢的 OpenCV 代码片段

大数据问题总结

数组中的第K个最大元素--力扣