Pythonでインスタンスメソッドをキャッシュする標準的な方法はありますか?


9

キャッシュしたいpythonスクリプトに計算集中型の関数がいくつかあります。私はスタックオーバーフローの解決策を探しに行き、たくさんのリンクを見つけました:

  1. /programming/4431703/python-resettable-instance-method-memoization-decorator
  2. https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
  3. http://pythonhosted.org/cachetools/
  4. https://pythonhosted.org/Flask-Cache/(私はこれをフラスコアプリケーションに使用しましたが、これはフラスコアプリケーションではありません)。

結局、これを自分のプログラムに貼り付けてしまいました。それは十分に単純に見えます-そしてうまく働きます。

class memoized(object):
    '''Decorator. Caches a function's return value each time it is called.
    If called later with the same arguments, the cached value is returned
    (not reevaluated).
    '''
    def __init__(self, func):
        self.func = func
        self.cache = {}

    def __call__(self, *args):
        if not isinstance(args, collections.Hashable):
            return self.func(*args)
        if args in self.cache:
            return self.cache[args]
        else:
            value = self.func(*args)
            self.cache[args] = value
            return value

    def __repr__(self):
        '''Return the function's docstring.'''
        return self.func.__doc__

    def __get__(self, obj, objtype):
        '''Support instance methods.'''
        return functools.partial(self.__call__, obj)

ただし、Pythonには正規のベストプラクティスがあるかどうかと思います。私はこれを処理するために非常に一般的に使用されるパッケージがあると想定し、これが存在しない理由について混乱しています。http://pythonhosted.org/cachetools/はバージョン.6のみであり、構文は他のソリューションのように単に@memoizeデコレータを追加するよりも複雑です。

回答:


12

これを行うための標準的な、Python特有の方法はありません。いずれにしても、私はそのことに気づいていません。そして、私は見た人であり、成功したメモパッケージの作者である人物として話しています

しかし、あなたが見つけた先行技術の欠如は、何よりも用語の問題かもしれないと思います。あなたはキャッシングを求めました。それは適切な用語ですが、広すぎます。特定の関数呼び出しまたはアクティビティの結果を後で使用するためにキャッシュすることを、より具体的にはメモ化またはメモ化と呼びます。そして確かに、コミュニティから利用可能な多くのメモ化パッケージと、多くのレシピがあります(たとえば、これ)。また、多くの多目的ユーティリティパッケージのメモ機能も見ました。それらの多くは成熟していて、戦いで強化され、常に「バージョン0.6のコード」ではなく、本番環境で常に使用されています。

なぜメモ化が標準的または慣用的に処理されないのか、私には言えません。おそらく、異なる長所とトレードオフでそれを達成するためのさまざまな方法があるためです。あるいは、すでに非常に多くの異なるアプローチが使用されているためかもしれません。他の言語コミュニティが熱心に集中しているが、特定のAPIにコミットするのではなく、レシピとして処理することを好むように思われるPythonコミュニティや能力など、機能を見つけることがよくあります。いずれの場合でも、コードが機能する場合は、成功したメモライザーのランクにようこそ!

更新

Python 3標準ライブラリ(3.2以降用)にはlru_cacheデコレータ(ここにドキュメント)が含まれているため、最も一般的なメモ化のユースケースを標準化するための最新の試みのように見えます。Pythonの進化の非常に遅い段階に来たことが、おそらく共通の解決策がない理由ですが、新しいコードの場合、それは、あなたが見つけることになる標準的なものに近いものです。


1
Python 3.8では、インスタンスの存続期間を通じて戻り値が同じであると予想されるメソッドに適している@cached_propertyデコレータが追加されまし
Patrick Brinich-Langlois

0

インスタンスメソッドは自己属性の使用、特にそれらの変更を許可されているため、メモ化された任意のインスタンスメソッドの正確性を保証することはできません。さらに、実装では、ハッシュ可能なオブジェクトに暗黙の制約を追加し、そのハッシュに応じてキャッシュヒットします。これを使用できるクラスと、メモ化されたメソッドを持つクラス(または継承するクラス)に追加できるフィールドに制限されます。

これらの理由により、関数をメモする必要がある場合は、高価なインスタンスメソッドを静的メソッドに変換し、必要なオブジェクト属性を引数として明示的に渡すことをお勧めします。これにより、クラスの設計を自由に行うことができ、キャッシュヒットを改善できます。これは、メモ化するコードの簡略化と一般化にも役立ちます。この設計には細粒度の実装が存在し、キャッシュサイズ、期間/無効化メソッドをカスタマイズして、スレッドの安全性、永続性を保証することができます...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.