2017-08-23 1 views
0

Je fais l'exercice de décorateur mémoized avec la fonction de fibonacci. La fonction mémoized devrait être beaucoup plus rapide quand l'entrée devient grande, parce qu'elle renvoie le résultat d'un dictionnaire au lieu de calculer le résultat encore.Le décorateur de mémo s'exécute plus lentement que la fonction originale

J'utilise timeit.timeit() pour mesurer le temps d'exécution de la fonction avec memoized on vs off. Le résultat obtenu est exactement le contraire de ce à quoi je m'attends. L'exécution sans le décorateur s'exécute beaucoup plus rapidement. Je cours des commandes sur la console de PyCharm python.

@With décorateur

>>> print(timeit.timeit('decorators.fibonacci(7)', setup='import decorators')) 
19.6940833939 
>>> print(timeit.timeit('decorators.fibonacci(10)', setup='import decorators')) 
85.7157191166 

sans le décorateur

>>> print(timeit.timeit('decorators.fibonacci(7)', setup='import decorators')) 
5.10131571594 
>>> print(timeit.timeit('decorators.fibonacci(10)', setup='import decorators')) 
21.9784012801 

J'ai couru les TimeIt plusieurs fois, je viens juste d'une sortie pour résumer. Qu'est-ce que je rate?

Merci

Mise à jour: Merci à la réponse de Daniel, je trouve mon erreur. J'ai déplacé la création du dictionnaire en dehors de l'emballage, et les résultats étaient bien meilleurs.

>>> print(timeit.timeit('decorators.fibonacci(10)', setup='import decorators')) 
0.248986574759 
+0

L'avez-vous fatigué pour des valeurs beaucoup plus grandes? Ma conjecture serait que pour 7 et 10 que peu de frais généraux introduit par mémoization est plus grand que le coût des calculs réels. Je suppose que pour fibbonacci (100), il peut donner des résultats attendus. –

+1

Serait-ce à cause de votre déclaration d'affirmation? Et en note, vous n'avez pas besoin de la déclaration de réussite à la fin. Vous pouvez vérifier le n négatif et générer une erreur, puis vérifier le scénario de base et le retour. Si les deux vérifications échouent, ce doit être le cas récursif, donc inutile d'utiliser autre chose. – Mai

+0

Mai ce petit changement rend le code plus facile à lire, merci pour la note – Vinny

Répondre

5

Vous créez un nouveau dictionnaire à chaque fois que la fonction est appelée, parce que votre fonction wrapper fait toujours wrapper.d = {}. Par conséquent, le cache ne sera jamais rempli, et votre code a l'avantage supplémentaire de créer le dictionnaire à chaque fois.

Cette ligne doit sortir de cette fonction avant de la renvoyer de mem_fib.

+0

Je ne sais pas comment j'ai raté ça, merci! quand j'ai déplacé la création du dictionnaire en dehors du wrapper (à l'intérieur de mem_fib) les résultats étaient comme prévu – Vinny

+0

'print (timeit.timeit ('decorators.fibonacci (10)', setup = 'import décorateurs')) 0.248986574759' – Vinny