私が欲しいのは、次のようなメモ化デコレータです。
- 引数とキーワード引数の両方でインスタンスメソッドをメモ化できます
- 1回の呼び出しで(グローバルに)クリアできるキャッシュがあります(関数ごとのキャッシュを使用するこのキャッシュ:python resettable instance method memoization decorator)
- かなり効率的です
私が見た例を微調整して、次のように思いつきました。
import functools
class Memoized(object):
"""Decorator that caches a function's return value each time it is called.
If called later with the same arguments, the cached value is returned, and
not re-evaluated.
"""
__cache = {}
def __init__(self, func):
self.func = func
self.key = (func.__module__, func.__name__)
def __call__(self, *args):
try:
return Memoized.__cache[self.key][args]
except KeyError:
value = self.func(*args)
Memoized.__cache[self.key] = {args : value}
return value
except TypeError:
# uncachable -- for instance, passing a list as an argument.
# Better to not cache than to blow up entirely.
return self.func(*args)
def __get__(self, obj, objtype):
"""Support instance methods."""
return functools.partial(self.__call__, obj)
@staticmethod
def reset():
Memoized.__cache = {}
それに関する私の問題は、キャッシング部分が多くのオーバーヘッドを伴うように見えることです(たとえば、再帰関数の場合)。次の関数を例として使用すると、メモ化されていないバージョンでは、メモ化されたバージョンよりも短い時間で fib(30) を 10 回呼び出すことができます。
def fib(n):
if n in (0, 1):
return n
return fib(n-1) + fib(n-2)
このデコレータを書くためのより良い方法を提案できる人はいますか? (または、私が望むことを行うより良い(つまり、より高速な)デコレータを教えてください)。メソッドのシグネチャを保持したり、イントロスペクション ツールが装飾された関数について「認識」できるようにすることには興味がありません。
ありがとう。
PS Python 2.7の使用