Caching¶
But de l’exercice¶
Le but de l’exercice est d’écrire un décorateur de fonction caching, dans un fichier caching.py dont le but est de mettre en cache le resultat d'une fonction.
Biensur, il serait facile d'utiliser le décorateur @cache fourni en standard par la librairie functools (voir la doc python), ou bien aussi le décorateur lru_cache (aussi sur la doc python); mais cela ne serait vraiment pas drôle...
Et voila le script de tests unitaires : test_caching.py
Exercice de base¶
Ecrire le décorateur de fonction de sorte qu'il permette de stocker le resultat d'une fonction afin de pouvoir le redonner lors d'un prochain appel.
Dans un premier temps il suffit juste de vérifier que cela fonctionne bien avec une fonction simple:
>>> @cache
... def simple():
... # Time consuming operation
... return 0
>>> simple()
0
>>> simple()
0
Maintenant que cette première étape est validée, il va falloir pouvoir traiter les fonctions qui prennent des arguments. Le but ici étant de faire en sorte de sauver les résultats associés à des arguments afin de redonner le bon résultat.
>>> @cache
... def simple2(index):
... # Time consuming operation
... return index
>>> simple2(1)
1
>>> simple2(10)
10
>>> simple2(1)
1
Parfois tout ne se passe pas comme prevu, et si on a des arguments qui ne sont pas identifiables, il faudra faire en sorte que la fonction donne tout de même le bon résultat.
Voila pour l'exercice de base.
Bonus numéro 1¶
Ajouter des compteurs afin de pouvoir savoir combien de fois notre système de caching a calculé effectivement un résultat computed_count , le nombre de fois où un résultat a été redonné sans calcul served_count et enfin le nombre d'appels qui ont échoués à être mis en cache missed_count.
>>> simple2(0)
0
>>> simple2.computed_count
1
>>> simple2.served_count
0
>>> simple2.missed_count
0
>>> simple2(0) + simple2(0)
0
>>> simple2.computed_count
1
>>> simple2.served_count
2
>>> simple2.missed_count
0
Bonus numéro 2¶
Faire en sorte que le doctext soit concervé malgré le décorateur.
>>> @cache
... def simple():
... """This is the documentation of simple function"""
... return 0
>>> simple.__doc__
'This is the documentation of simple function'
Bonus numéro 3¶
Faire en sorte de ne stocker qu'un certain nombre de résultats afin de ne pas saturer la mémoire..
>>> @cache(3)
... def simple2(idx):
... return idx
>>> list((simple(i) for i in range(5))
[0, 1, 2, 3, 4]
>>> simple2.computed_count
5
>>> list((simple(i) for i in range(3, 5))
[3, 4]
>>> simple2.computed_count
5
>>> list((simple(i) for i in range(5))
[0, 1, 2, 3, 4]
>>> simple2.computed_count
10
Aide¶
Si vraiment vous êtes bloqué·e·s, vous pouvez regarder ces articles :
- Decorators - PEP-0318
- Comprendre les décorateurs
- Hashing en python
- Wrap decorator
- Decorators with arguments