Existe uma maneira canônica de armazenar em cache os métodos de instância em python?

5

Eu tenho algumas funções computacionalmente intensivas no meu script python que gostaria de armazenar em cache. Eu fui procurar soluções em estouro de pilha e encontrei muitos links:

  1. link
  2. link
  3. link
  4. link (usei este para aplicativos de balão, mas este não é um aplicativo de frasco).

No final, acabei colando isso no meu programa. Parece bastante simples - e funciona bem.

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)

No entanto, estou querendo saber se existe uma melhor prática canônica no Python. Eu acho que eu assumi que haveria um pacote muito comumente usado para lidar com isso e estou confuso sobre por que isso não existe. O link é apenas na versão .6 e a sintaxe é mais complexa do que simplesmente adicionar um @memoize decorator, como em outras soluções.

    
por bernie2436 28.10.2014 / 17:23
fonte

1 resposta

8

Não existe uma maneira canônica e única de fazer isso Python. Nenhum dos quais eu estou ciente, de qualquer forma - e eu estou falando como alguém que olhou, e quem é o autor de um pacote de memorandos bem-sucedido .

No entanto, acredito que a sua falta de arte prévia encontrada pode ser uma questão de terminologia, tanto quanto qualquer outra coisa. Você pediu armazenamento em cache . Esse é um termo apropriado, mas é excessivamente amplo. Armazenar em cache os resultados de uma determinada chamada de função ou atividade para uso posterior é mais especificamente chamado de memoizing ou memoization . E, de fato, há muitos pacotes de memoizing disponíveis na comunidade , bem como muitas receitas ( por exemplo, esta ). Eu também vi funções de memorando em muitos pacotes de utilitário multiuso. Muitos deles são maduros, endurecidos pela batalha e constantemente usados na produção - não apenas "código da versão 0.6".

Por que o memoizing não é mais canonicamente ou manuseado de maneira idiomática, não posso dizer. Talvez porque existem várias maneiras de realizá-lo com virtudes e compensações diferentes. Ou talvez porque já existem tantas abordagens diferentes em uso. Muitas vezes eu encontro recursos - "achatar uma lista de listas" é outra - que outras comunidades linguísticas convergem ansiosamente, mas que a comunidade ou os poderes do Python parecem preferir manipular como receitas em vez de se comprometer com uma API específica. Em qualquer caso, se o seu código funcionar, seja bem-vindo ao grupo de memoizers de sucesso!

Atualizar

Como a biblioteca padrão do Python 3 (para o 3.2 e posterior) inclui um decorador lru_cache ( documentação aqui ), eu tenho que dizer que parece uma tentativa recente de padronizar o caso de uso de memorização mais comum. O fato de ter chegado tão tarde na evolução do Python é provavelmente o porquê de não haver uma solução comum, mas, para um novo código, é o mais próximo possível do canônico que você encontrará.

    
por 28.10.2014 / 17:44
fonte

Tags