我找到了这个很好的memoizing装饰器:
http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
特定的应用程序是人工智能,它将存在于一个不可变的状态类中。问题是我通过返回父状态的copy.copy执行运算符的应用程序,并应用了请求的运算符。 copy.copy节省了大量浪费的时间,因为大部分状态与其父级相同。
现在,这是我的问题。如果我在类中使用上面的memoization类,那些会记忆到可能无效值的函数的memoized副本是否会被传递?我认为我需要以某种方式使memoized副本无效。
答案 0 :(得分:1)
是。 copy.copy
很浅,所以它只是复制对memoizing包装器对象的引用。如果删除__get__
的{{1}}方法,则可以尝试这样做(否则,您将获得用于支持绑定方法的memoized
对象):
partial
您可以在需要时(即复制时)构建新的包装器:class C(object):
@memoized
def foo(): pass
o1 = C()
o2 = copy.copy(o1)
print o1.foo.cache is o2.foo.cache
。
答案 1 :(得分: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