Python 记住非递归函数结果

Python 记住非递归函数结果,python,Python,我有一个代价高昂的非递归函数,我希望将结果存储到字典中,从而通过在字典中检查结果来节省时间 该函数有3个参数: def slow_func(a,b,c) 目前,我正在deque中保存一个对象: memory = deque([], 1000) ... {(a,b,c):result}, {(a,b,c):result}, {(a,b,c):result} 我检查字典中是否有a,b,c,然后显示结果 有没有更快的方法保存结果 编辑: 输入几乎有40%的时间是不同的。 输入a和b为numpy.n

我有一个代价高昂的非递归函数,我希望将结果存储到字典中,从而通过在字典中检查结果来节省时间

该函数有3个参数:

def slow_func(a,b,c)
目前,我正在deque中保存一个对象:

memory = deque([], 1000)
...
{(a,b,c):result}, {(a,b,c):result}, {(a,b,c):result}
我检查字典中是否有a,b,c,然后显示结果

有没有更快的方法保存结果

编辑:

输入几乎有40%的时间是不同的。 输入a和b为numpy.ndarray 返回是numpy.ndarray
编辑:OP已经更新了这个问题以包含数据类型,但我将保留答案,因为它可能对其他人有用

如果a、b、c的数据类型是不可变的,则元组是可以的,列表是不可变的。为此,有一个内置的函数修饰符:

from functools import lru_cache

@lru_cache(maxsize=None)
def slow_func(a,b,c):
      ....

编辑:OP已经更新了这个问题以包含数据类型,但我将保留答案,因为它可能对其他人有用

如果a、b、c的数据类型是不可变的,则元组是可以的,列表是不可变的。为此,有一个内置的函数修饰符:

from functools import lru_cache

@lru_cache(maxsize=None)
def slow_func(a,b,c):
      ....

为了将numpy.array等类型的缓存用作函数参数(可更改且不可散列),可以使用以下解决方案:

from functools import lru_cache, wraps
import numpy as np


def np_cache(*args, **kwargs):
    """LRU cache implementation for functions whose FIRST parameter is a numpy array"""
    def decorator(function):
        @wraps(function)
        def wrapper(np_array, *args, **kwargs):
            hashable_array = array_to_tuple(np_array)
            return cached_wrapper(hashable_array, *args, **kwargs)

        @lru_cache(*args, **kwargs)
        def cached_wrapper(hashable_array, *args, **kwargs):
            array = tuple(map(tuple, np_array))
            return function(array, *args, **kwargs)

        def array_to_tuple(np_array):
            """Iterates recursivelly."""
            try:
                return tuple(array_to_tuple(_) for _ in np_array)
            except TypeError:
                return np_array

        # copy lru_cache attributes over too
        wrapper.cache_info = cached_wrapper.cache_info
        wrapper.cache_clear = cached_wrapper.cache_clear

        return wrapper

    return decorator
用法:

array = np.array([[1, 2, 3], [4, 5, 6]])

# use decorator to cache
@np_cache(maxsize=256)
def multiply(array, factor):
    print("Calculating...")
    return factor*array

# execute function once 
multiply(array, 2)
计算

数组[[2,4,6],[8,10,12]]

计算

数组[[2,4,6],[8,10,12]]

CacheInfohits=1,misses=1,maxsize=256,currsize=1


git代码。

要将numpy.array等类型的缓存用作函数参数(可变且不可散列),可以使用以下解决方案:

from functools import lru_cache, wraps
import numpy as np


def np_cache(*args, **kwargs):
    """LRU cache implementation for functions whose FIRST parameter is a numpy array"""
    def decorator(function):
        @wraps(function)
        def wrapper(np_array, *args, **kwargs):
            hashable_array = array_to_tuple(np_array)
            return cached_wrapper(hashable_array, *args, **kwargs)

        @lru_cache(*args, **kwargs)
        def cached_wrapper(hashable_array, *args, **kwargs):
            array = tuple(map(tuple, np_array))
            return function(array, *args, **kwargs)

        def array_to_tuple(np_array):
            """Iterates recursivelly."""
            try:
                return tuple(array_to_tuple(_) for _ in np_array)
            except TypeError:
                return np_array

        # copy lru_cache attributes over too
        wrapper.cache_info = cached_wrapper.cache_info
        wrapper.cache_clear = cached_wrapper.cache_clear

        return wrapper

    return decorator
用法:

array = np.array([[1, 2, 3], [4, 5, 6]])

# use decorator to cache
@np_cache(maxsize=256)
def multiply(array, factor):
    print("Calculating...")
    return factor*array

# execute function once 
multiply(array, 2)
计算

数组[[2,4,6],[8,10,12]]

计算

数组[[2,4,6],[8,10,12]]

CacheInfohits=1,misses=1,maxsize=256,currsize=1



git代码。

输入a、b、c总是相同的还是唯一的?为什么是deque而不是字典?我循环了1000个存储值,所以我决定使用deque。a、 b和c相当大返回的类型是什么?返回是np。ndarraya输入a、b、c总是相同的还是唯一的?为什么是deque而不是字典?我循环了1000个存储值,所以我决定使用deque。a、 b和c相当大返回的类型是什么?返回是np.ndarrayThanks Christian,我也想到了lru缓存。我得到TypeError:不可损坏的类型。我可能应该做一个定制的装饰器。当我回答时,你还没有输入数据类型。是的,它不适用于可变数据类型:因为字典用于缓存结果,所以函数的位置参数和关键字参数必须是可散列的。对不起,Christian,我在编辑问题时就想到了这一点,但不是及时的。谢谢Christian,我也想到了lru_缓存。我得到TypeError:不可损坏的类型。我可能应该做一个定制的装饰器。当我回答时,你还没有输入数据类型。是的,它不适用于可变数据类型:因为字典用于缓存结果,所以函数的位置参数和关键字参数必须是可哈希的。抱歉,我在编辑问题时就想到了这一点,但没有按时完成。出于好奇:这比您原来的方法快多少?几乎三个调用中有一个被缓存。这是一个错误:NameError:name'np_array'未定义。这是一个在线数组=tuplemaptuple,np_数组好奇的是:与原始方法相比,它的速度有多快?几乎三分之一的调用被缓存。这里有一个错误:NameError:没有定义名称“np_数组”。它是在线数组=tuplemaptuple,np\u数组