通常、オブジェクトをコピーすると正確なクローンが作成されます。値がキャッシュされている場合は、それらもコピーする必要があります。これを行わない場合、通常はディープ コピーの速度を最適化するためのものであり、目に見える副作用はありません。
何かのコピーを作成していて、コピー内のキャッシュされた値をクリアしたい場合は、キャッシュを明示的にクリアする必要があります。
オブジェクトのコピーがキャッシュをコピーしないようにする場合は、__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