我的意见是错了/误导性的,不涉及到lru_cache
,但任何试图创建一个高速缓存功能,更多的一般工作。
我面临需要一种高速缓存功能,对于功能工作输入和输出NumPy
阵列,其是可变的,而不是可哈希。由于NumPy
数组不可散列,因此我无法使用functools.lru_cache
。我结束了wroting是这样的:
def mutable_cache(maxsize=10):
"""In-memory cache like functools.lru_cache but for any object
This is a re-implementation of functools.lru_cache. Unlike
functools.lru_cache, it works for any objects, mutable or not.
Therefore, it returns returns a copy and it is wrong if the mutable
object has changed! Use with caution!
If you call the *resulting* function with a keyword argument
'CLEAR_CACHE', the cache will be cleared. Otherwise, cache is rotated
when more than `maxsize` elements exist in the cache. Additionally,
if you call the resulting function with NO_CACHE=True, it doesn't
cache at all. Be careful with functions returning large objects.
Everything is kept in RAM!
Args:
maxsize (int): Maximum number of return values to be remembered.
Returns:
New function that has caching implemented.
"""
sentinel = object()
make_key = functools._make_key
def decorating_function(user_function):
cache = {}
cache_get = cache.get
keylist = [] # don't make it too long
def wrapper(*args, **kwds):
if kwds.get("CLEAR_CACHE"):
del kwds["CLEAR_CACHE"]
cache.clear()
keylist.clear()
if kwds.get("NO_CACHE"):
del kwds["NO_CACHE"]
return user_function(*args, **kwds)
elif "NO_CACHE" in kwds:
del kwds["NO_CACHE"]
key = str(args) + str(kwds)
result = cache_get(key, sentinel)
if result is not sentinel:
# make sure we return a copy of the result; when a = f();
# b = f(), users should reasonably expect that a is not b.
return copy.copy(result)
result = user_function(*args, **kwds)
cache[key] = result
keylist.append(key)
if len(keylist) > maxsize:
try:
del cache[keylist[0]]
del keylist[0]
except KeyError:
pass
return result
return functools.update_wrapper(wrapper, user_function)
return decorating_function
在我的第一个版本,我已经省略了copy.copy()
功能(这确实应该copy.deepcopy()
),而导致的错误,如果我改变所产生的价值,然后回顾了cached-功能。在我添加了copy.copy()
功能之后,我意识到我在某些情况下占用了内存,主要是因为我的函数计数的是对象,而不是总内存使用量,这在一般情况下在Python中是不平凡的(尽管应该很容易,如果限制为NumPy
阵列)。因此,我将NO_CACHE
和CLEAR_CACHE
关键字添加到了所产生的函数中,这些函数完成了它们的名称。
编写并使用此函数之后,我明白functools.lru_cache
仅适用于具有可哈希输入参数的函数的原因不止一个。任何需要使用可变参数的缓存函数的人都需要非常小心。
感谢您的回答! – Jonathan