2

私はこの素敵なメモ化デコレータを見つけました:

http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize

特定のアプリケーションは人工知能であり、不変の状態クラス内に存在します。問題は、要求されたオペレーターが適用された状態で、親状態の copy.copy を返すことによって、オペレーターの適用を実行することです。copy.copy は、ほとんどの状態がその親と同じであるため、無駄になる時間を大幅に節約します。

さて、ここに私の問題があります。クラス内で上記のメモ化クラスを使用すると、潜在的に無効な値にメモ化される関数のメモ化されたコピーが渡されますか? どうにかしてメモ化されたコピーを無効にする必要があると思います。

4

2 に答える 2

1

はい。copy.copy浅いので、メモ化ラッパーオブジェクトへの参照をコピーするだけです。__get__のメソッドを削除すると、次のように試すことができますmemoized(そうしないと、partialバインドされたメソッドをサポートするために使用されるオブジェクトが取得されます)。

class C(object):
    @memoized
    def foo(): pass

o1 = C()
o2 = copy.copy(o1)
print o1.foo.cache is o2.foo.cache

必要に応じて (つまり、コピーするとき)、新しいラッパーを作成できますmemoized(C.foo.func)

于 2011-03-18T16:26:38.193 に答える
1

通常、オブジェクトをコピーすると正確なクローンが作成されます。値がキャッシュされている場合は、それらもコピーする必要があります。これを行わない場合、通常はディープ コピーの速度を最適化するためのものであり、目に見える副作用はありません。

何かのコピーを作成していて、コピー内のキャッシュされた値をクリアしたい場合は、キャッシュを明示的にクリアする必要があります。

オブジェクトのコピーがキャッシュをコピーしないようにする場合は、__copy__または__deepcopy__メソッドを定義してコピーを制御します。(これの通常の使用は、ファイル記述子やハンドルなどの基になるリソースをコピーするためであることに注意してください。)これを行うことはお勧めしません。

両方の例を次に示します。

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.
    """
    def __init__(self, func):
        self.func = func
        self.cache = {}
    def __copy__(self):
        """
        Don't copy the cache in a copy.
        """
        return memoized(self.func)
    def __deepcopy__(self, memo):
        """
        Don't copy the cache in a deep copy.
        """
        return memoized(self.func)

    def __call__(self, *args):
       try:
           return self.cache[args]
       except KeyError:
           value = self.func(*args)
           self.cache[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 __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)
    def clear_cache(self):
        self.cache = {}

@memoized
def fibonacci(n):
    "Return the nth fibonacci number."
    if n in (0, 1):
        return n
    return fibonacci(n-1) + fibonacci(n-2)

fibonacci(12)
print fibonacci.cache
fibonacci.clear_cache()
print fibonacci.cache

fibonacci(12)
print fibonacci.cache
import copy
f = copy.deepcopy(fibonacci)
print f.cache
于 2011-03-18T16:27:00.253 に答える