Основываясь на ответе на оригинальный вопрос, данный @aix, я создал класс, который, я думаю, мог бы его улучшить. Основная особенность заключается в том, что кэшированные значения хранятся как свойство экземпляра, метод которого оформляется, поэтому их очень легко сбросить.
class memoize(object):
def __init__(self, func):
#print "Init"
self.func = func
def __call__(self, *args):
#print "Call"
if not self.func in self.cache:
self.cache[self.func] = {}
try:
return self.cache[self.func][args]
except KeyError:
value = self.func(*args)
self.cache[self.func][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."""
#print "Get", obj, objtype
fn = functools.partial(self.__call__, obj)
try:
self.cache = obj.cache
except:
obj.cache = {}
self.cache = obj.cache
#print self.cache
return fn
В качестве примера использования:
class MyClass(object):
def __init__(self,data):
self.data = data
def update(self,data):
self.data = data
self.cache = {}
@memoize
def func1(self,x):
print "Computing func1"
return "I am func1 of %s. Data is %s. x is %s\n" % (self, self.data, x)
@memoize
def func2(self,x):
print "Computing func2"
return "I am func2 of %s. Data is %s. x is %s\n" % (self, self.data, x)
def func3(self,x):
print "Computing func3"
return "I am func3 of %s. Data is %s. x is %s\n" % (self, self.data, x)
mc1 = MyClass("data1")
mc2 = MyClass("data2")
mc3 = MyClass("data3")
print mc1.func1(1)
print mc1.func1(1)
print mc1.func2(1)
print mc1.func2(1)
print mc1.func3(1)
print mc1.func3(1)
print mc2.func1(1)
print mc2.func1(1)
print mc2.func2(1)
print mc2.func2(1)
print mc2.func3(1)
print mc2.func3(1)
print "Update mc1\n"
mc1.update("data1new")
print mc1.func1(1)
print mc1.func2(1)
print mc1.func3(1)
print mc2.func1(1)
print mc2.func2(1)
print mc2.func3(1)
получает в качестве вывода:
Computing func1
I am func1 of <__main__.MyClass object at 0x100470fd0>. Data is data1. x is 1
I am func1 of <__main__.MyClass object at 0x100470fd0>. Data is data1. x is 1
Computing func2
I am func2 of <__main__.MyClass object at 0x100470fd0>. Data is data1. x is 1
I am func2 of <__main__.MyClass object at 0x100470fd0>. Data is data1. x is 1
Computing func3
I am func3 of <__main__.MyClass object at 0x100470fd0>. Data is data1. x is 1
Computing func3
I am func3 of <__main__.MyClass object at 0x100470fd0>. Data is data1. x is 1
Computing func1
I am func1 of <__main__.MyClass object at 0x100476050>. Data is data2. x is 1
I am func1 of <__main__.MyClass object at 0x100476050>. Data is data2. x is 1
Computing func2
I am func2 of <__main__.MyClass object at 0x100476050>. Data is data2. x is 1
I am func2 of <__main__.MyClass object at 0x100476050>. Data is data2. x is 1
Computing func3
I am func3 of <__main__.MyClass object at 0x100476050>. Data is data2. x is 1
Computing func3
I am func3 of <__main__.MyClass object at 0x100476050>. Data is data2. x is 1
Update mc1
Computing func1
I am func1 of <__main__.MyClass object at 0x100470fd0>. Data is data1new. x is 1
Computing func2
I am func2 of <__main__.MyClass object at 0x100470fd0>. Data is data1new. x is 1
Computing func3
I am func3 of <__main__.MyClass object at 0x100470fd0>. Data is data1new. x is 1
I am func1 of <__main__.MyClass object at 0x100476050>. Data is data2. x is 1
I am func2 of <__main__.MyClass object at 0x100476050>. Data is data2. x is 1
Computing func3
I am func3 of <__main__.MyClass object at 0x100476050>. Data is data2. x is 1