Il n'y a rien de particulièrement inefficace ou compliqué sur la façon dont vous avez implémenté votre mise en cache; c'est essentiellement ce qui doit arriver. Cependant, ce n'est pas vraiment général.
Vous pouvez implémenter une sorte de stratégie de mise en cache plus généralisée, en utilisant des décorateurs si vous le souhaitez, par commodité. Une approche possible pourrait être:
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
impression:
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])
L'inconvénient bien sûr, de mettre en œuvre la mise en cache hors de votre objet, est que les données du cache ne soit pas effacé lorsque votre objet disparaît , sauf si vous prenez quelques précautions pour que cela se produise.
Le bloc try except ne sera plus efficace que s'il s'attend à atteindre le cache plus de 99% du temps. http://stackoverflow.com/questions/3111195/python-performance-try-except-or-not-in – Wilduck
@Wilduck: Ce test n'a pas pris en compte le temps nécessaire à la méthode _calculate dans un environnement de mise en cache, qui est susceptible de rendre la question «pas dans/essayer/obtenir» plutôt marginale. Les repères de l'application réelle sont indiqués. –
Vous avez raison. Tous mes benchmarks ont indiqué que tout type de réglage suggéré dans l'une des réponses ici n'a aucun impact mesurable sur les performances (bien que la mise en cache de base que j'ai implémentée donne une augmentation de performance x3 sur un petit ensemble de données). –