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つのインスタンスすべてに対して1つのLRUキャッシュではなく、3つの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を使用したり、レシピをコピーしてコードに貼り付ける代わりにPyPIを使用したりできるようにしたい場合)、1つの明白な解決策がありますfunctools.lru_cachefunctools32:インスタンスごとに新しい装飾されたインスタンスメソッドを作成します。

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 に答える