Considere o seguinte:
@property
def name(self):
if not hasattr(self, '_name'):
# expensive calculation
self._name = 1 + 1
return self._name
Sou novo, mas acho que o armazenamento em cache pode ser fatorado em um decorador. Só que eu não encontrei um igual;)
PS o cálculo real não depende de valores mutáveis
python
caching
decorator
memoization
Tobias
fonte
fonte
Respostas:
A partir do Python 3.2, existe um decorador embutido:
@functools.lru_cache(maxsize=100, typed=False)
Exemplo de um cache LRU para calcular números de Fibonacci :
Se você está preso ao Python 2.x, aqui está uma lista de outras bibliotecas de memoização compatíveis:
functools32
| PyPI | Código fonterepoze.lru
| PyPI | Código fontepylru
| PyPI | Código fontebackports.functools_lru_cache
| PyPI | Código fontefonte
lru_cache
fazer uma cópia de qualquer resultado em cache, e nenhuma cópia está sendo feita nafunctools.lru_cache
implementação. Isso também correria o risco de criar problemas de memória difíceis de encontrar quando usados para armazenar em cache um objeto grande.Parece que você não está solicitando um decorador de memorização de uso geral (ou seja, não está interessado no caso geral em que deseja armazenar em cache valores de retorno para diferentes valores de argumento). Ou seja, você gostaria de ter o seguinte:
enquanto um decorador de memorização de uso geral daria a você o seguinte:
Eu afirmo que a sintaxe da chamada de método tem um estilo melhor, porque sugere a possibilidade de computação cara, enquanto a sintaxe da propriedade sugere uma pesquisa rápida.
[Atualização: o decorador de memorização baseado em classe ao qual vinculei e citei aqui anteriormente não funciona para métodos. Substituí-lo por uma função decoradora.] Se você deseja usar um decorador de memorização de uso geral, aqui está uma simples:
Exemplo de uso:
Outro decorador de memorização com um limite no tamanho do cache pode ser encontrado aqui .
fonte
fibonacci
. Essa função sempre usa o mesmomemo
dicionário.Usos da amostra:
fonte
functools.cached_property
Decorador Python 3.8https://docs.python.org/dev/library/functools.html#functools.cached_property
cached_property
do Werkzeug foi mencionado em: https://stackoverflow.com/a/5295190/895245, mas uma versão supostamente derivada será mesclada no 3.8, o que é incrível.Esse decorador pode ser visto como armazenamento em cache
@property
ou como um limpador@functools.lru_cache
para quando você não tiver argumentos.Os documentos dizem:
fonte
Werkzeug tem um
cached_property
decorador ( documentos , fonte )fonte
Eu codifiquei essa classe simples de decorador para armazenar em cache as respostas das funções. Acho MUITO útil para meus projetos:
O uso é direto:
fonte
@cached
está faltando parênteses. Então ele só irá retornar ocached
objeto no lugar domyfunc
e quando chamado comomyfunc()
, em seguida,inner
será sempre retornado como um valor de retornoAVISO LEGAL: Eu sou o autor de kids.cache .
Você deve verificar
kids.cache
, ele fornece um@cache
decorador que funciona no python 2 e python 3. Sem dependências, ~ 100 linhas de código. É muito simples de usar, por exemplo, com seu código em mente, você pode usá-lo assim:Então
Ou você pode colocar o
@cache
decorador após o@property
(mesmo resultado).O uso de cache em uma propriedade é chamado de avaliação lenta ,
kids.cache
pode fazer muito mais (funciona na função com argumentos, propriedades, qualquer tipo de método e até classe ...). Para usuários avançados,kids.cache
suportecachetools
que fornece armazenamentos de cache sofisticados para python 2 e python 3 (cache LRU, LFU, TTL, RR).NOTA IMPORTANTE : o armazenamento em cache padrão de
kids.cache
é um ditado padrão, que não é recomendado para programas de longa duração com consultas sempre diferentes, pois isso levaria a um armazenamento em cache cada vez maior. Para esse uso, você pode conectar outros repositórios de cache usando, por exemplo (@cache(use=cachetools.LRUCache(maxsize=2))
para decorar sua função / propriedade / classe / método ...)fonte
c
deMyClass
, e inspeccioná-la comobjgraph.show_backrefs([c], max_depth=10)
, há uma cadeia de ref a partir do objecto de classeMyClass
ac
. Ou seja,c
nunca seria lançado até oMyClass
lançamento.Ah, só precisava encontrar o nome certo para isso: " Avaliação preguiçosa da propriedade ".
Eu também faço muito isso; talvez eu use essa receita no meu código em algum momento.
fonte
Existe o fastcache , que é "A implementação em C do Python 3 functools.lru_cache. Fornece uma aceleração de 10 a 30x na biblioteca padrão".
O mesmo que a resposta escolhida , apenas importação diferente:
Além disso, ele é instalado no Anaconda , ao contrário das funções que precisam ser instaladas .
fonte
functools
faz parte da biblioteca padrão, o link que você postou é um garfo git aleatório ou algo mais ...Há ainda outro exemplo de decorador de memoize no Python Wiki:
http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
Esse exemplo é um pouco inteligente, porque não armazenará em cache os resultados se os parâmetros forem mutáveis. (verifique esse código, é muito simples e interessante!)
fonte
Se você estiver usando o Django Framework, ele possui essa propriedade para armazenar em cache uma visualização ou resposta do uso da API
@cache_page(time)
e também pode haver outras opções.Exemplo:
Mais detalhes podem ser encontrados aqui .
fonte
Junto com o exemplo Memoize , encontrei os seguintes pacotes python:
fonte
Eu implementei algo assim, usando pickle para persistência e sha1 para identificações curtas, quase certamente únicas. Basicamente, o cache hash o código da função e o histórico dos argumentos para obter um sha1 e, em seguida, procurou um arquivo com esse sha1 no nome. Se existia, abriu e retornou o resultado; caso contrário, ele chama a função e salva o resultado (opcionalmente, salvando apenas se levar um certo tempo para processar).
Dito isso, eu juro que encontrei um módulo existente que fez isso e me encontro aqui tentando encontrá-lo ... O mais próximo que posso encontrar é esse, que parece certo: http: //chase-seibert.github. io / blog / 2011/11/23 / pythondjango-disk-based-caching-decorator.html
O único problema que vejo com isso é que não funcionaria bem para entradas grandes, pois hashes str (arg), que não é exclusivo para matrizes gigantes.
Seria bom se houvesse um protocolo unique_hash () que tivesse uma classe retornando um hash seguro de seu conteúdo. Basicamente, implementei isso manualmente para os tipos que me interessavam.
fonte
Tente joblib http://pythonhosted.org/joblib/memory.html
fonte
Se você estiver usando o Django e quiser armazenar em cache as visualizações, consulte a resposta de Nikhil Kumar .
Mas se você deseja armazenar em cache QUALQUER resultado de função, você pode usar django-cache-utils .
Ele reutiliza os caches do Django e fornece um
cached
decorador fácil de usar :fonte
@lru_cache
não é perfeito com valores de função padrãomeu
mem
decorador:e código para teste:
resultado - apenas 3 vezes com sono
mas com
@lru_cache
isso será 4 vezes, porque isso:será calculado duas vezes (mau trabalho com padrões)
fonte