C’è un decoratore semplicemente cache funzione dei valori di ritorno?
Si consideri il seguente:
@property
def name(self):
if not hasattr(self, '_name'):
# expensive calculation
self._name = 1 + 1
return self._name
Io sono nuovo, ma penso che la cache potrebbe essere fattorizzato in un decoratore. Solo non mi piace 😉
PS il calcolo vero e proprio non dipendono i valori modificabili
- Ci può essere un decoratore là fuori che ha una certa capacità di simile, ma non completamente specificata ciò che si desidera. Che tipo di memorizzazione nella cache di backend stai usando? E come sarà il valore digitato? Sto assumendo da codice che cosa si sta realmente chiedendo è la cache di una proprietà di sola lettura.
- Ci sono memoizing decoratori che eseguire ciò che è chiamata “cache”; di solito lavoro su funzioni come tale (se vuole diventare metodi o non), i cui risultati dipendono da loro argomenti (non modificabile cose come auto!-) e in modo da tenere separati memo-dict.
A partire da Python 3.2 vi è un built-in decoratore:
@functools.lru_cache(maxsize=100, digitato=False)
Esempio di LRU cache per il calcolo I numeri di Fibonacci:
Se si sono bloccati con Python 2.x, ecco qui di seguito un elenco di altri compatibili memoization librerie:
functools32
| PyPI | Il codice sorgenterepoze.lru
| PyPI | Il codice sorgentepylru
| PyPI | Il codice sorgentebackports.functools_lru_cache
| PyPI | Il codice sorgentelru_cache
per fare una copia di ciò che il risultato è la cache, e non tale copia è stata fatta infunctools.lru_cache
attuazione. Così facendo, inoltre, rischiano di creare hard-to-find problemi di memoria quando viene utilizzato per la cache di un oggetto di grandi dimensioni.lru_cache
funzione. Penso mutevole hashable oggetti sono piuttosto rare in ogni caso. Scusate per la confusione!!!Sembra che tu stia non chiedere un general-purpose memoization decoratore (cioè, non siete interessati al caso generale in cui si desidera memorizzare i valori di ritorno per diversi valori dell’argomento). Che è, ti piacerebbe avere questo:
mentre un general-purpose memoization decoratore di dare è questo:
Credo che il metodo-la sintassi di chiamata è un migliore stile, perché suggerisce la possibilità di costosi calcolo, mentre la sintassi della proprietà suggerisce una ricerca rapida.
[Aggiornamento: La classe base memoization decoratore avevo legato e qui citato in precedenza non funziona per i metodi. L’ho sostituito con un decoratore funzione.] Se siete disposti a utilizzare un general-purpose memoization decoratore, ecco un semplice:
Esempio di utilizzo:
Un altro memoization decoratore con un limite sulla dimensione della cache può essere trovato qui.
memo = {}
in funzionememorize
. Poi quando chiami diversifibonacci
, ilfibonacci
s chiamare lo stesso decoratorememorize
?fibonacci
. La funzione utilizza sempre la stessamemo
dizionario.Esempio si utilizza:
Werkzeug ha un
cached_property
decoratore (docs, fonte)Ho codificato questo semplice decoratore classe a funzione di cache le risposte. Io la trovo MOLTO utile per i miei progetti:
L’utilizzo è molto semplice:
@cached
manca la parentesi. Altrimenti saranno solo restituire ilcached
oggetto dimyfunc
e quando è stato chiamato comemyfunc()
poiinner
verrà sempre restituito come valore di ritornoPython 3.8
cached_property
decoratorehttps://docs.python.org/dev/library/functools.html#functools.cached_property
cached_property
da Werkzeug è stato menzionato all’: https://stackoverflow.com/a/5295190/895245 ma presumibilmente versione derivata unita 3.8, che è impressionante.Questo decoratore può essere visto come la memorizzazione nella cache
@property
, o come addetto@functools.lru_cache
per quando non si hanno argomenti.Docs dire:
DISCLAIMER: io sono l’autore di ragazzi.cache.
Si dovrebbe verificare
kids.cache
, esso fornisce un@cache
decoratore che funziona su python 2 e python 3. Dipendenze, ~100 righe di codice. E ‘ molto semplice da usare, per esempio, con il codice in mente, si potrebbe utilizzare come questa:Poi
O si potrebbe mettere il
@cache
decoratore dopo il@property
(stesso risultato).L’utilizzo della cache su una proprietà è chiamato lazy evaluation,
kids.cache
può fare molto di più (funziona su una funzione con argomenti, proprietà, qualsiasi tipo di metodi, e anche le classi…). Per gli utenti avanzati,kids.cache
supportacachetools
che fornisce fantasia cache memorizza per python 2 e python 3 (LRU, LFU, TTL, RR cache).NOTA IMPORTANTE: la cache predefinita negozio di
kids.cache
è uno standard dict, che non è raccomandato per il lungo programma in esecuzione, con sempre diverse query in quanto porterebbe ad una sempre crescente di memorizzazione nella cache store. Per questo tipo di utilizzo è possibile plugin altre cache memorizza usando, per esempio, (@cache(use=cachetools.LRUCache(maxsize=2))
per decorare la vostra funzione/struttura/classe/metodo…)c
diMyClass
, e controllare conobjgraph.show_backrefs([c], max_depth=10)
, c’è un ref catena dalla classe objectMyClass
perc
. Che dire,c
non sarebbe mai stato rilasciato fino a quando ilMyClass
stato rilasciato.Ah, solo bisogno di trovare il nome giusto per questo: “Pigro di valutazione immobiliare“.
Mi faccio un sacco di troppo; forse userò la ricetta nel mio codice di volte.
C’è ancora un altro esempio di un memoize decoratore a Python Wiki:
http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
Che l’esempio è un po ‘ intelligente, perché non in cache i risultati, se i parametri sono modificabili. (controllare che il codice è molto semplice e interessante!)
Se si utilizza il Framework Django, ha una proprietà di questo tipo di cache di vista o di risposta delle API
utilizzando
@cache_page(time)
e ci possono essere altre opzioni come bene.Esempio:
Ulteriori dettagli possono essere trovati qui.
Insieme con il Memoize Esempio ho trovato i seguenti pacchetti di python:
C’è fastcache, che è “C implementazione di Python 3 functools.lru_cache. Fornisce un aumento di velocità di 10-30x su libreria standard.”
Stesso risposta scelta, solo di importazione diversi:
Inoltre, viene installato nel Anaconda, a differenza di functools che deve essere installato.
Ho implementato qualcosa di simile a questo, con la salamoia per la costanza e l’utilizzo sha1 per brevi quasi certamente-Id univoci. Fondamentalmente la cache hash il codice della funzione e l’hist di argomenti per avere una sha1 poi ho cercato un file con un sha1 nel nome. Se esistesse, si è aperto ed è tornato il risultato; se non lo è, si chiama la funzione e salva il risultato (facoltativamente solo di salvare se ha preso una certa quantità di tempo per il processo).
Detto questo, mi piacerebbe giuro ho trovato un modulo esistente che ha fatto questo e mi trovo qui a cercare di trovare quel modulo… Il più vicino che posso trovare è questo, che sembra sul diritto: http://chase-seibert.github.io/blog/2011/11/23/pythondjango-disk-based-caching-decorator.html
L’unico problema che vedo è che non funziona bene per le grandi ingressi in quanto hash str(arg), che non è unico per il gigante di matrici.
Sarebbe bello se ci fosse un unique_hash() protocollo che aveva una classe in un secure hash del suo contenuto. In pratica ho implementato manualmente che per le tipologie di cui mi interessasse.
@lru_cache
non è perfetto con funzione di default i valorimio
mem
decoratore:e il codice per il test:
risultato – solo 3 volte con il sonno
ma con
@lru_cache
sarà 4 volte, a causa di questo:sarà calcolato due volte (un po ‘ con le impostazioni predefinite)
Provare joblib
http://pythonhosted.org/joblib/memory.html
Se si utilizza Django e desidera cache di vista, vedere Nikhil Kumar risposta.
Ma se si desidera memorizzare QUALSIASI risultato di una funzione, è possibile utilizzare django-cache-utils.
Riutilizza Django cache e fornisce un facile da usare
cached
decoratore: