Python numpy阵列的缓存装饰器
我正在尝试为带有numpy数组输入参数的函数制作一个缓存装饰器Python numpy阵列的缓存装饰器,python,python-3.x,numpy,caching,decorator,Python,Python 3.x,Numpy,Caching,Decorator,我正在尝试为带有numpy数组输入参数的函数制作一个缓存装饰器 from functools import lru_cache import numpy as np from time import sleep a = np.array([1,2,3,4]) @lru_cache() def square(array): sleep(1) return array * array square(a) 但是numpy数组是不可散列的 TypeError
from functools import lru_cache
import numpy as np
from time import sleep
a = np.array([1,2,3,4])
@lru_cache()
def square(array):
sleep(1)
return array * array
square(a)
但是numpy数组是不可散列的
TypeError Traceback (most recent call last)
<ipython-input-13-559f69d0dec3> in <module>()
----> 1 square(a)
TypeError: unhashable type: 'numpy.ndarray'
但我想用一个装饰师来包装这一切,到目前为止我已经尝试过:
def np_cache(function):
def outter(array):
array_hashable = tuple(array)
@lru_cache()
def inner(array_hashable_inner):
array_inner = np.array(array_hashable_inner)
return function(array_inner)
return inner(array_hashable)
return outter
@np_cache
def square(array):
sleep(1)
return array * array
但是,缓存不起作用。计算已执行,但未正确缓存,因为我总是等待1秒
我错过了什么?我猜lru\u cache
没有获得正确的上下文并在每次调用中实例化它,但我不知道如何修复它
我曾试图盲目地抛出
functools.wrapps
装饰程序,但运气不好。您的包装函数每次调用时都会创建一个新的内部()
函数。此时新函数对象被修饰,因此最终结果是每次调用outter()
,都会创建一个新的lru\u缓存()
,该缓存将为空。空缓存将始终必须重新计算该值
您需要创建一个装饰器,将缓存附加到每个装饰目标只创建一次的函数。如果要在调用缓存之前转换为元组,则必须创建两个函数:
from functools import lru_cache, wraps
def np_cache(function):
@lru_cache()
def cached_wrapper(hashable_array):
array = np.array(hashable_array)
return function(array)
@wraps(function)
def wrapper(array):
return cached_wrapper(tuple(array))
# copy lru_cache attributes over too
wrapper.cache_info = cached_wrapper.cache_info
wrapper.cache_clear = cached_wrapper.cache_clear
return wrapper
cached\u wrapper()
函数在每次调用np\u cache()
时仅创建一次,并作为闭包提供给wrapper()
函数。所以wrapper()
调用cached\u wrapper()
,它附带了一个@lru\u cache()
,缓存元组
我还复制了lru\u cache
放在修饰函数上的两个函数引用,因此它们也可以通过返回的包装器访问
此外,我还使用跨元数据从原始函数对象复制到包装器,例如名称、注释和文档字符串。这始终是一个好主意,因为这意味着在调试时以及需要访问文档或注释时,您的修饰函数将在回溯中清楚地标识出来。装饰程序还添加了一个
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>属性,指向原始函数,这将是。我想补充的是,通过将数组赋给np\u cache()中定义的非局部变量,您可以在wrapper()和cashed\u wrapper()之间共享数组,这样,你不能。它不是线程安全的。您无法确定传递给cached\u wrapper()
的是同一数组的元组值版本。这两个函数之间共享的任何闭包都应该被视为每个被修饰的函数范围内的全局闭包。
from functools import lru_cache, wraps
def np_cache(function):
@lru_cache()
def cached_wrapper(hashable_array):
array = np.array(hashable_array)
return function(array)
@wraps(function)
def wrapper(array):
return cached_wrapper(tuple(array))
# copy lru_cache attributes over too
wrapper.cache_info = cached_wrapper.cache_info
wrapper.cache_clear = cached_wrapper.cache_clear
return wrapper