Folgendes berücksichtigen:
@property
def name(self):
if not hasattr(self, '_name'):
# expensive calculation
self._name = 1 + 1
return self._name
Ich bin neu, aber ich denke, das Caching könnte in einen Dekorateur zerlegt werden. Nur habe ich so etwas nicht gefunden;)
PS: Die tatsächliche Berechnung hängt nicht von veränderlichen Werten ab
python
caching
decorator
memoization
Tobias
quelle
quelle
Antworten:
Ab Python 3.2 gibt es einen eingebauten Dekorator:
@functools.lru_cache(maxsize=100, typed=False)
Beispiel eines LRU-Cache zur Berechnung von Fibonacci-Zahlen :
Wenn Sie mit Python 2.x nicht weiterkommen, finden Sie hier eine Liste anderer kompatibler Memoization-Bibliotheken:
functools32
| PyPI | Quellcoderepoze.lru
| PyPI | Quellcodepylru
| PyPI | Quellcodebackports.functools_lru_cache
| PyPI | Quellcodequelle
lru_cache
, muss eine Kopie des Caching-Ergebnisses erstellt werden, und in derfunctools.lru_cache
Implementierung wird keine solche Kopie erstellt . Andernfalls besteht die Gefahr, dass beim Zwischenspeichern eines großen Objekts schwer zu findende Speicherprobleme auftreten.Es hört sich so an, als würden Sie nicht nach einem universellen Memoization Decorator fragen (dh Sie interessieren sich nicht für den allgemeinen Fall, in dem Sie Rückgabewerte für verschiedene Argumentwerte zwischenspeichern möchten). Das heißt, Sie möchten dies haben:
Ein Allzweck-Memoisierungsdekorateur würde Ihnen Folgendes geben:
Ich behaupte, dass die Methodenaufrufsyntax einen besseren Stil hat, da sie die Möglichkeit einer teuren Berechnung nahe legt, während die Eigenschaftssyntax eine schnelle Suche vorschlägt.
[Update: Der klassenbasierte Memoization Decorator, mit dem ich zuvor verlinkt und hier zitiert habe, funktioniert nicht für Methoden. Ich habe es durch eine Dekorationsfunktion ersetzt.] Wenn Sie bereit sind, einen Allzweck-Memoisierungsdekorator zu verwenden, ist hier eine einfache:
Anwendungsbeispiel:
Ein weiterer Memoization Decorator mit einer Begrenzung der Cache-Größe finden Sie hier .
quelle
fibonacci
. Diese Funktion verwendet immer das gleichememo
Wörterbuch.Beispielverwendungen:
quelle
Python 3.8
functools.cached_property
Dekorateurhttps://docs.python.org/dev/library/functools.html#functools.cached_property
cached_property
von Werkzeug wurde erwähnt unter: https://stackoverflow.com/a/5295190/895245 aber eine angeblich abgeleitete Version wird in 3.8 zusammengeführt, was großartig ist.Dieser Dekorateur kann als Caching
@property
oder als Reiniger angesehen werden@functools.lru_cache
wenn Sie keine Argumente haben.Die Dokumente sagen:
quelle
Werkzeug hat einen
cached_property
Dekorateur ( docs , Quelle )quelle
Ich habe diese einfache Dekorationsklasse codiert, um Funktionsantworten zwischenzuspeichern. Ich finde es SEHR nützlich für meine Projekte:
Die Verwendung ist unkompliziert:
quelle
@cached
fehlt Klammer. Andernfalls wird dascached
Objekt nur anstelle von zurückgegeben,myfunc
und wenn es aufgerufenmyfunc()
wird,inner
wird es immer als Rückgabewert zurückgegebenHAFTUNGSAUSSCHLUSS: Ich bin der Autor von kids.cache .
Sie sollten überprüfen
kids.cache
, es bietet einen@cache
Dekorator, der auf Python 2 und Python 3 funktioniert. Keine Abhängigkeiten, ~ 100 Codezeilen. Es ist sehr einfach zu verwenden, zum Beispiel mit Blick auf Ihren Code, Sie könnten es so verwenden:Dann
Oder Sie könnten den
@cache
Dekorateur nach dem setzen@property
(gleichen Ergebnis) setzen.Die Verwendung des Cache für eine Eigenschaft wird als verzögerte Auswertung bezeichnet und
kids.cache
kann viel mehr (sie funktioniert für Funktionen mit beliebigen Argumenten, Eigenschaften, Methoden aller Art und sogar Klassen ...). Für fortgeschrittene Benutzerkids.cache
Unterstützung,cachetools
die Python 2 und Python 3 (LRU-, LFU-, TTL-, RR-Cache) mit ausgefallenen Cache-Speichern versorgt.WICHTIGER HINWEIS : Der Standard-Cache-Speicher von
kids.cache
ist ein Standard-Diktat, das nicht für Programme mit langer Laufzeit und immer unterschiedlichen Abfragen empfohlen wird, da dies zu einem ständig wachsenden Caching-Speicher führen würde. Für diese Verwendung können Sie beispielsweise andere Cache-Speicher einbinden (@cache(use=cachetools.LRUCache(maxsize=2))
um Ihre Funktion / Eigenschaft / Klasse / Methode zu dekorieren ...).quelle
c
vonMyClass
und überprüft sie mitobjgraph.show_backrefs([c], max_depth=10)
einer Ref-Kette vom KlassenobjektMyClass
zuc
. Das heißt,c
würde nie veröffentlicht werden, bis dieMyClass
veröffentlicht wurden.Ah, ich musste nur den richtigen Namen dafür finden: " Lazy Property Evaluation ".
Ich mache das auch viel; Vielleicht verwende ich dieses Rezept irgendwann in meinem Code.
quelle
Es gibt Fastcache , dh "C-Implementierung von Python 3 functools.lru_cache. Bietet eine 10-30-fache Beschleunigung gegenüber der Standardbibliothek."
Gleich wie gewählte Antwort , nur anderer Import:
Außerdem wird es in Anaconda installiert, im Gegensatz zu functools, die installiert werden müssen .
quelle
functools
ist Teil der Standardbibliothek, der Link, den Sie gepostet haben, führt zu einer zufälligen Git-Gabel oder etwas anderem ...Es gibt noch ein weiteres Beispiel für einen Memoize- Dekorateur im Python-Wiki:
http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
Dieses Beispiel ist etwas klug, da die Ergebnisse nicht zwischengespeichert werden, wenn die Parameter veränderbar sind. (Überprüfen Sie diesen Code, es ist sehr einfach und interessant!)
quelle
Wenn Sie Django Framework verwenden, verfügt es über eine solche Eigenschaft, um eine Ansicht oder Antwort der verwendeten APIs zwischenzuspeichern,
@cache_page(time)
und es kann auch andere Optionen geben.Beispiel:
Weitere Details finden Sie hier .
quelle
Zusammen mit dem Memoize-Beispiel habe ich die folgenden Python-Pakete gefunden:
quelle
Ich habe so etwas implementiert, indem ich pickle für die Persistenz und sha1 für kurze, mit ziemlicher Sicherheit eindeutige IDs verwendet habe. Grundsätzlich hat der Cache den Code der Funktion und die Historie der Argumente gehasht, um eine sha1 zu erhalten, und dann nach einer Datei mit dieser sha1 im Namen gesucht. Wenn es existierte, öffnete es es und gab das Ergebnis zurück; Wenn nicht, ruft es die Funktion auf und speichert das Ergebnis (optional nur, wenn die Verarbeitung eine gewisse Zeit in Anspruch genommen hat).
Trotzdem würde ich schwören, dass ich ein vorhandenes Modul gefunden habe, das dies getan hat, und mich hier befinde, um dieses Modul zu finden ... Das nächste, das ich finden kann, ist das, das ungefähr richtig aussieht: http: //chase-seibert.github. io / blog / 2011/11/23 / pythondjango-disk-based-caching-decorator.html
Das einzige Problem, das ich dabei sehe, ist, dass es für große Eingaben nicht gut funktioniert, da es str (arg) hasht, was für riesige Arrays nicht eindeutig ist.
Es wäre schön, wenn es ein unique_hash () -Protokoll gäbe , bei dem eine Klasse einen sicheren Hash ihres Inhalts zurückgibt . Ich habe das für die Typen, die mir wichtig waren, im Grunde manuell implementiert.
quelle
Probieren Sie joblib http://pythonhosted.org/joblib/memory.html aus
quelle
Wenn Sie Django verwenden und Ansichten zwischenspeichern möchten, lesen Sie die Antwort von Nikhil Kumar .
Wenn Sie jedoch JEDE Funktionsergebnisse zwischenspeichern möchten, können Sie django-cache-utils verwenden .
Es verwendet Django-Caches wieder und bietet einen benutzerfreundlichen
cached
Dekorator:quelle
@lru_cache
ist mit Standardfunktionswerten nicht perfektmein
mem
Dekorateur:und Code zum Testen:
Ergebnis - nur 3 mal mit Schlaf
aber
@lru_cache
damit wird es 4 mal sein, denn das:wird zweimal berechnet (schlechtes Arbeiten mit Standardeinstellungen)
quelle