2

我发现了这个不错的记忆装饰器:

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

特定的应用程序是在人工智能中,它将存在于一个不可变的状态类中。问题是我通过返回父状态的副本来执行运算符的应用,并应用了请求的运算符。copy.copy 节省了大量原本会被浪费的时间,因为大部分状态与其父状态相同。

现在,这是我的问题。如果我要在类中使用上面的 memoization 类,是否会传递 memoize 到潜在无效值的函数的 memoized 副本?我想我需要以某种方式使记忆副本无效。

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 回答