Ich habe einige rechenintensive Funktionen in meinem Python-Skript, die ich zwischenspeichern möchte. Ich habe nach Lösungen für den Stapelüberlauf gesucht und viele Links gefunden:
- /programming/4431703/python-resettable-instance-method-memoization-decorator
- https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
- http://pythonhosted.org/cachetools/
- https://pythonhosted.org/Flask-Cache/ (Ich habe dieses für Kolbenanwendungen verwendet, aber dieses ist keine Kolbenanwendung).
Am Ende habe ich dies in mein Programm eingefügt. Es scheint einfach genug - und funktioniert gut.
class memoized(object):
'''Decorator. Caches a function's return value each time it is called.
If called later with the same arguments, the cached value is returned
(not reevaluated).
'''
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
if not isinstance(args, collections.Hashable):
return self.func(*args)
if args in self.cache:
return self.cache[args]
else:
value = self.func(*args)
self.cache[args] = value
return value
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)
Ich frage mich jedoch, ob es in Python eine kanonische Best Practice gibt. Ich denke, ich habe angenommen, dass es ein sehr häufig verwendetes Paket geben würde, um dies zu handhaben, und bin verwirrt darüber, warum dies nicht existiert. http://pythonhosted.org/cachetools/ ist nur in Version .6 verfügbar und die Syntax ist komplexer als das einfache Hinzufügen eines @ memoize-Dekorators, wie in anderen Lösungen.
@cached_property
Decorator hinzugefügt , der besser für Methoden geeignet ist, deren Rückgabewerte voraussichtlich während der gesamten Lebensdauer der Instanz gleich bleiben.Da eine Instanzmethode Selbstattribute verwenden und insbesondere ändern darf, können Sie die Richtigkeit einer beliebigen gespeicherten Instanzmethode nicht garantieren. Darüber hinaus fügt Ihre Implementierung eine implizite Einschränkung für Ihr Objekt hinzu, die hashbar sein soll, und abhängig von diesem Hash ist der Cache-Treffer begrenzt. Sie können nur Klassen verwenden, die Sie verwenden können, und Felder, die Sie Klassen hinzufügen können, die eine gespeicherte Methode haben (oder eine erben).
Wenn Sie sich eine Funktion merken müssen, ist es aus diesen Gründen besser, die teure Instanzmethode in eine statische Methode umzuwandeln und die erforderlichen Objektattribute explizit als Argumente an sie zu übergeben. Dies gibt Ihnen die Freiheit beim Klassendesign und kann den Cache-Treffer verbessern. Dies hilft auch, den Memo-Code zu vereinfachen und zu verallgemeinern. Für dieses Design gibt es feinkörnige Implementierungen, mit denen Sie manchmal die Cache-Größe, die Dauer / die Ungültigmachungsmethoden anpassen können, um die Thread-Sicherheit, die Beständigkeit ...
quelle