Considérer ce qui suit:
@property
def name(self):
if not hasattr(self, '_name'):
# expensive calculation
self._name = 1 + 1
return self._name
Je suis nouveau, mais je pense que la mise en cache pourrait être prise en compte dans un décorateur. Seulement je n'en ai pas trouvé un comme ça;)
PS le calcul réel ne dépend pas des valeurs mutables
python
caching
decorator
memoization
Tobias
la source
la source
Réponses:
À partir de Python 3.2, il existe un décorateur intégré:
@functools.lru_cache(maxsize=100, typed=False)
Exemple de cache LRU pour le calcul des nombres de Fibonacci :
Si vous êtes bloqué avec Python 2.x, voici une liste d'autres bibliothèques de mémorisation compatibles:
functools32
| PyPI | Code sourcerepoze.lru
| PyPI | Code sourcepylru
| PyPI | Code sourcebackports.functools_lru_cache
| PyPI | Code sourcela source
lru_cache
faire une copie du résultat de sa mise en cache, et aucune copie de ce type n'est effectuée dans l'functools.lru_cache
implémentation. Cela risquerait également de créer des problèmes de mémoire difficiles à trouver lorsqu'il est utilisé pour mettre en cache un objet volumineux.Il semble que vous ne demandiez pas un décorateur de mémorisation à usage général (c'est-à-dire que vous n'êtes pas intéressé par le cas général où vous voulez mettre en cache les valeurs de retour pour différentes valeurs d'argument). Autrement dit, vous aimeriez avoir ceci:
tandis qu'un décorateur de mémorisation polyvalent vous donnerait ceci:
Je soumets que la syntaxe d'appel de méthode est un meilleur style, car elle suggère la possibilité d'un calcul coûteux tandis que la syntaxe de propriété suggère une recherche rapide.
[Mise à jour: Le décorateur de mémorisation basé sur les classes que j'avais lié et cité ici précédemment ne fonctionne pas pour les méthodes. Je l'ai remplacé par une fonction de décorateur.] Si vous êtes prêt à utiliser un décorateur de mémorisation à usage général, en voici une simple:
Exemple d'utilisation:
Un autre décorateur de mémorisation avec une limite sur la taille du cache peut être trouvé ici .
la source
fibonacci
. Cette fonction utilise toujours le mêmememo
dictionnaire.Exemples d'utilisations:
la source
functools.cached_property
Décorateur Python 3.8https://docs.python.org/dev/library/functools.html#functools.cached_property
cached_property
de Werkzeug a été mentionné à l' adresse : https://stackoverflow.com/a/5295190/895245 mais une version supposée dérivée sera fusionnée dans 3.8, ce qui est génial.Ce décorateur peut être considéré comme une mise en cache
@property
ou comme un nettoyeur@functools.lru_cache
lorsque vous n'avez aucun argument.Les documents disent:
la source
Werkzeug a un
cached_property
décorateur ( docs , source )la source
J'ai codé cette classe de décorateur simple pour mettre en cache les réponses des fonctions. Je le trouve TRÈS utile pour mes projets:
L'utilisation est simple:
la source
@cached
est sans parenthèse. Sinon, il ne renverra l'cached
objet qu'à la place demyfunc
et lorsqu'il est appelé commemyfunc()
alors, ilinner
sera toujours retourné comme valeur de retourAVERTISSEMENT: je suis l'auteur de kids.cache .
Vous devriez vérifier
kids.cache
, il fournit un@cache
décorateur qui fonctionne sur python 2 et python 3. Pas de dépendances, ~ 100 lignes de code. C'est très simple à utiliser, par exemple, avec votre code à l'esprit, vous pouvez l'utiliser comme ceci:ensuite
Ou vous pouvez mettre le
@cache
décorateur après le@property
(même résultat).L'utilisation du cache sur une propriété est appelée évaluation paresseuse ,
kids.cache
peut faire beaucoup plus (cela fonctionne sur la fonction avec tous les arguments, propriétés, tout type de méthodes, et même les classes ...). Pour les utilisateurs avancés,kids.cache
prend en chargecachetools
qui fournit des magasins de cache sophistiqués pour python 2 et python 3 (cache LRU, LFU, TTL, RR).REMARQUE IMPORTANTE : le magasin de cache par défaut de
kids.cache
est un dict standard, ce qui n'est pas recommandé pour les programmes de longue durée avec des requêtes toujours différentes car cela conduirait à un magasin de mise en cache toujours croissant. Pour cette utilisation, vous pouvez ajouter d'autres magasins de cache en utilisant par exemple (@cache(use=cachetools.LRUCache(maxsize=2))
pour décorer votre fonction / propriété / classe / méthode ...)la source
c
deMyClass
, et l'inspecte avecobjgraph.show_backrefs([c], max_depth=10)
, il existe une chaîne de références de l'objet de classeMyClass
àc
. C'est-à-dire qu'ilsc
n'auraient jamais été libérés tant qu'ils ne l'avaient pasMyClass
été.Ah, juste besoin de trouver le bon nom pour cela: " Lazy property evaluation ".
Je fais beaucoup ça aussi; peut-être que j'utiliserai cette recette dans mon code un jour.
la source
Il y a fastcache , qui est "l'implémentation C de functools.lru_cache Python 3. Fournit une accélération de 10-30x par rapport à la bibliothèque standard."
Identique à la réponse choisie , juste une importation différente:
En outre, il est installé dans Anaconda , contrairement aux functools qui doivent être installés .
la source
functools
fait partie de la bibliothèque standard, le lien que vous avez posté est vers un git fork aléatoire ou autre chose ...Il y a encore un autre exemple de décorateur de mémorisation sur Python Wiki:
http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
Cet exemple est un peu intelligent, car il ne mettra pas en cache les résultats si les paramètres sont mutables. (vérifiez ce code, c'est très simple et intéressant!)
la source
Si vous utilisez Django Framework, il a une telle propriété pour mettre en cache une vue ou une réponse de l'utilisation de l'API
@cache_page(time)
et il peut également y avoir d'autres options.Exemple:
Plus de détails peuvent être trouvés ici .
la source
Avec l' exemple Memoize, j'ai trouvé les packages python suivants:
la source
J'ai implémenté quelque chose comme ça, en utilisant pickle pour la persistance et en utilisant sha1 pour des identifiants courts, presque certainement uniques. Fondamentalement, le cache a haché le code de la fonction et l'historique des arguments pour obtenir un sha1, puis a cherché un fichier avec ce sha1 dans le nom. S'il existait, il l'ouvrit et retourna le résultat; sinon, il appelle la fonction et enregistre le résultat (en option, sauvegarde uniquement si le traitement a pris un certain temps).
Cela dit, je jurerais que j'ai trouvé un module existant qui a fait cela et je me retrouve ici à essayer de trouver ce module ... Le plus proche que je puisse trouver est celui-ci, qui semble à peu près correct: http: //chase-seibert.github. io / blog / 2011/11/23 / pythondjango-disk-based-caching-decorator.html
Le seul problème que je vois avec cela est que cela ne fonctionnerait pas bien pour les grandes entrées car il hache str (arg), ce qui n'est pas unique pour les tableaux géants.
Ce serait bien s'il y avait un protocole unique_hash () qui avait une classe renvoyant un hachage sécurisé de son contenu. Je l'ai essentiellement implémenté manuellement pour les types qui m'intéressaient.
la source
Essayez joblib http://pythonhosted.org/joblib/memory.html
la source
Si vous utilisez Django et souhaitez mettre en cache des vues, consultez la réponse de Nikhil Kumar .
Mais si vous voulez mettre en cache N'IMPORTE QUEL résultat de fonction, vous pouvez utiliser django-cache-utils .
Il réutilise les caches Django et fournit un
cached
décorateur facile à utiliser :la source
@lru_cache
n'est pas parfait avec les valeurs de fonction par défautmon
mem
décorateur:et code pour les tests:
résultat - seulement 3 fois avec le sommeil
mais avec
@lru_cache
ce sera 4 fois, car ceci:sera calculé deux fois (mauvais fonctionnement avec les valeurs par défaut)
la source