46

使用此处找到的 LRU 缓存装饰器:http: //code.activestate.com/recipes/578078-py26-and-py30-backport-of-python-33s-lru-cache/

from lru_cache import lru_cache
class Test:
    @lru_cache(maxsize=16)
    def cached_method(self, x):
         return x + 5

我可以用它创建一个装饰类方法,但它最终会创建一个全局缓存,适用于类 Test 的所有实例。但是,我的意图是为每个实例创建一个缓存。因此,如果我要实例化 3 个测试,我将拥有 3 个 LRU 缓存,而不是所有 3 个实例的 1 个 LRU 缓存。

我知道这种情况发生的唯一迹象是,当在不同的类实例修饰方法上调用 cache_info() 时,它们都返回相同的缓存统计信息(鉴于它们正在与非常不同的参数进行交互,这种情况极不可能发生):

CacheInfo(hits=8379, misses=759, maxsize=128, currsize=128)
CacheInfo(hits=8379, misses=759, maxsize=128, currsize=128)
CacheInfo(hits=8379, misses=759, maxsize=128, currsize=128)

是否有一个装饰器或技巧可以让我轻松地让这个装饰器为每个类实例创建一个缓存?

4

3 回答 3

55

假设您不想修改代码(例如,因为您希望能够仅移植到 3.3 并使用 stdlib functools.lru_cache,或者使用functools32out PyPI 而不是将配方复制并粘贴到您的代码中),有一个明显的解决方案:为每个实例创建一个新的装饰实例方法。

class Test:
    def cached_method(self, x):
         return x + 5
    def __init__(self):
         self.cached_method = lru_cache(maxsize=16)(self.cached_method)
于 2013-02-18T22:31:16.573 回答
3

这个怎么样:一个函数装饰器,它在每个实例上第一次调用它时包装方法lru_cache

def instance_method_lru_cache(*cache_args, **cache_kwargs):
    def cache_decorator(func):
        @wraps(func)
        def cache_factory(self, *args, **kwargs):
            print('creating cache')
            instance_cache = lru_cache(*cache_args, **cache_kwargs)(func)
            instance_cache = instance_cache.__get__(self, self.__class__)
            setattr(self, func.__name__, instance_cache)
            return instance_cache(*args, **kwargs)
        return cache_factory
    return cache_decorator

像这样使用它:

class Foo:
    @instance_method_lru_cache()
    def times_2(self, bar):
        return bar * 2

foo1 = Foo()
foo2 = Foo()

print(foo1.times_2(2))
# creating cache
# 4
foo1.times_2(2)
# 4

print(foo2.times_2(2))
# creating cache
# 4
foo2.times_2(2)
# 4

这是 GitHub 上的要点和一些内联文档。

于 2016-09-02T14:47:45.547 回答
1

这些天,methodtools将工作

from methodtools import lru_cache
class Test:
    @lru_cache(maxsize=16)
    def cached_method(self, x):
         return x + 5

你需要安装methodtools

pip install methodtools

If you are still using py2, then functools32 also is required

pip install functools32
于 2019-05-05T11:02:48.520 回答