Voici comment vous pouvez mémoriser une fonction Python:
def memo_square(a, cache={}): if a not in cache: cache[a] = a*a return cache[a]
L'accueil est à juste titre peu connu, donc sous la coupe, nous analyserons comment cela fonctionne et à quoi il sert.
Tout d'abord, comment et pourquoi cela fonctionne.
memo_square
(comme toute autre fonction) est un objet de la classe de fonction, qui, entre autres attributs, a un
memo_square.__defaults__
rempli lors de la création de l'objet. Tout d'abord, il contient un dictionnaire vide, comme indiqué dans l'en-tête de la fonction:
>>> memo_square.__defaults__ ({},)
__defaults__
est un tuple régulier et vous ne pouvez pas modifier ses éléments. Certes, vous pouvez remplacer l'ensemble des valeurs par défaut en une seule fois, mais uniquement par un autre tuple:
>>> 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, cet article n'arrivera pas à Picaba. Eh bien, ce n'est pas important. L'important est qu'à l'exception du code très délicat,
func.__defaults__
est créé une fois pendant la durée du programme avec tous ses éléments. Un tuple et ses éléments ne seront pas recréés à chaque appel de fonction, ils seront utilisés tant que la fonction existera. Mais pour changer, si les éléments eux-mêmes sont mutables, personne ne les interdit. L'incapacité à travailler avec de tels éléments est l'
une des façons les plus courantes de se tirer une balle dans le python . Mais la sauvegarde de valeurs entre les appels de fonction peut être très utile. Après plusieurs appels,
memo_square.__defaults__
ressemblera à ceci:
>>> 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},)
Si la fonction a déjà été appelée pour la même valeur, la valeur est calculée et, par conséquent, le cache n'est pas réapprovisionné. Pour un carré, l'avantage est faible (à proprement parler, pour un carré, l'avantage est négatif, car la recherche dans un dictionnaire est plus coûteuse que la multiplication de deux nombres), mais pour des fonctions vraiment chères, la mémorisation / mise en cache peut être utile. Bien sûr, vous pouvez le fournir en python de plusieurs manières. Voici les alternatives que nous avons:
La principale chose que cette méthode de mémorisation perd, c'est qu'elle n'est pas très idiomatique. Personnellement, lorsque je suis tombé sur cette décision pour la première fois, j'ai réfléchi quelques minutes à ce qui se passait ici et pourquoi. D'un autre côté, au cours de ces quelques minutes, j'ai commencé à mieux comprendre comment les fonctions Python et leurs arguments sont organisés. Donc, même si vous n'utilisez pas les arguments par défaut (pour la mémorisation ou, par exemple, pour
accélérer la résolution de noms ), connaître cette technique est toujours utile pour tout nutritionniste.