É assim que você pode memorizar uma função Python:
def memo_square(a, cache={}): if a not in cache: cache[a] = a*a return cache[a]
A recepção é imerecidamente pouco conhecida; portanto, analisaremos como funciona e para que serve.
Primeiro, como e por que funciona.
memo_square
(como qualquer outra função) é um objeto da classe de função, que, entre outros atributos, possui uma tupla
memo_square.__defaults__
preenchida ao criar o objeto. Primeiro, ele contém um dicionário vazio, conforme indicado no cabeçalho da função:
>>> memo_square.__defaults__ ({},)
__defaults__
é uma tupla regular e você não pode alterar seus elementos. É verdade que você pode substituir todo o conjunto de valores padrão de uma só vez, mas apenas para outra tupla:
>>> def test(a=1, b=2): ... print(a, b) ... >>> test.__defaults__ (1, 2) >>> test() 1 2 >>> test.__defaults__ = (', ', '') >>> test() , >>> test.__defaults__[1] = '' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment >>> test.__defaults__ = {0: ', ', 1: ''} Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: __defaults__ must be set to a tuple object
Soryan, este artigo não chegará a Picaba. Bem, tudo bem, isso não é importante. O importante é que, com exceção do código muito esperto, a
func.__defaults__
é criada uma vez durante o tempo do programa com todos os seus elementos. Uma tupla e seus elementos não serão recriados a cada chamada de função, eles serão usados enquanto a função existir. Mas, para mudar, se os elementos em si são mutáveis, ninguém os proíbe. Incapacidade de trabalhar com esses elementos é
uma das maneiras mais comuns de se matar no python . Mas, na verdade, salvar valores entre chamadas de função pode ser bastante útil. Após várias chamadas,
memo_square.__defaults__
terá a seguinte aparência:
>>> memo_square(2) 4 >>> memo_square.__defaults__ ({2: 4},) >>> memo_square(5) 25 >>> memo_square.__defaults__ ({2: 4, 5: 25},) >>> memo_square(2) 4 >>> memo_square.__defaults__ ({2: 4, 5: 25},)
Se a função já tiver sido chamada para o mesmo valor, o valor será calculado e, portanto, o cache não será reabastecido. Para um quadrado, o benefício é pequeno (estritamente falando, para um quadrado, o benefício é negativo, porque pesquisar em um dicionário é mais caro do que multiplicar dois números), mas, por funções realmente caras, a memorização / armazenamento em cache pode ser útil. Obviamente, você pode fornecê-lo em python de mais de uma maneira. Aqui estão as alternativas que temos:
A principal coisa que esse método de memorização perde é que não é muito idiomático. Pessoalmente, quando me deparei com essa decisão pela primeira vez, pensei por alguns minutos sobre o que estava acontecendo aqui e por quê. Por outro lado, nesses minutos, comecei a entender um pouco melhor como o Python funciona e seus argumentos são organizados. Portanto, mesmo que você não use os argumentos padrão (para memorização ou, por exemplo, para
acelerar a resolução de nomes ), conhecer essa técnica ainda é útil para qualquer nutricionista.