關於如何實現緩存,沒有什麼特別低效或複雜的;這基本上是需要發生的事情。但是,這並不是很通常的。
爲方便起見,您可以實現某種更廣義的緩存策略,如果喜歡,可以使用裝飾器。一個可行的方法可能是:
class Memoizer(object):
def __init__(self):
self._cache = dict()
def memoize_unordered(self, f):
def wrapper(s, *args, **kwargs):
key = (s, f, frozenset(args), frozenset(kwargs.iteritems()))
if key not in self._cache:
print 'calculating', args, kwargs
self._cache[key] = f(s, *args, **kwargs)
return self._cache[key]
return wrapper
def memoize_ordered(self, f):
def wrapper(s, *args, **kwargs):
key = (s, f, tuple(args), frozenset(kwargs.iteritems()))
if key not in self._cache:
print 'calculating', args, kwargs
self._cache[key] = f(s, *args, **kwargs)
return self._cache[key]
return wrapper
memoizer = Memoizer()
class Foo(object):
@memoizer.memoize_unordered
def foo(self, a, b):
return self._calculate(a, b)
def _calculate(self, a, b):
return frozenset([a,b])
foo = Foo()
results = [foo.foo(*a) for a in [(1, 5), (1, 5), (5, 1), (9, 12), (12, 9)]]
for result in results:
print 'RESULT', result
印刷:
calculating (1, 5) {}
calculating (9, 12) {}
RESULT frozenset([1, 5])
RESULT frozenset([1, 5])
RESULT frozenset([1, 5])
RESULT frozenset([9, 12])
RESULT frozenset([9, 12])
當然缺點,你的對象之外實現緩存,就是當你的對象消失緩存中的數據沒有被刪除,除非你謹慎地做到這一點。
只有當他預計超過99%的時間才能訪問緩存時,try塊的效率纔會更高。 http://stackoverflow.com/questions/3111195/python-performance-try-except-or-not-in – Wilduck 2010-07-08 21:29:31
@Wilduck:該基準沒有考慮緩存環境中的_calculate方法花費的時間,其中很可能會使「不在/嘗試/獲得」問題變得相當微不足道。指出了實際應用的基準。 – 2010-07-08 22:18:25
你說得對。我所有的基準都表明,在這裏的任何答案中提出的任何類型的調整都沒有任何可衡量的性能影響(雖然我實現的基本緩存給小數據集帶來了x3性能提升)。 – 2010-07-09 08:12:53