2011-04-04 5 views
1

J'ai une fonction qui est appelée à environ 1742 fois mais quand je fais un décorateur pour calculer chaque temps d'appel de celui-ci, j'ai trouvé qu'il imprime seulement 647 fois je ne sais pas pourquoi cela se produit.Python fonction décorateur appels

Mise à jour:

  • Mon problème est pas ici comment faire sa synchronisation avec la différence entre le nombre d'appels, je veux un moyen de faire un décorateur comme fonction qui ont des appels précis.

  • Ma version python est 2.6 et voici le module je travaille sur http://pastebin.com/MXu1pLWM

  • Dans la sortie de profilage j'ai trouvé que la fonction de l'appelant à la fonction décorée appelle seulement 647 et il a été la seule fonction de l'appelant !!

À comprendre!

  • La fonction que je décore ont une boucle avec une longueur de 1742, mais les appels réels à la fonction est seulement 647, bien que je comprends toujours pas pourquoi il dit 1742 dans la section des appels au lieu de 647 :)

number = 0 
def timing(f): 
    def wrap(*args): 
     time1 = time.time() 
     ret = f(*args) 
     time2 = time.time() 
     global number 
     number+=1 
     print '%s function took %0.6f ms No of calls: %s' % (f.func_name, ((time2-time1)), str(number)) 
     return ret 
    return wrap 
+4

C'est une façon horrible de chronométrer les appels de fonction. Jetez un oeil aux profileurs python: http://docs.python.org/library/profile.html – ChristopheD

+0

Ce n'est pas comme ça que vous faites le profilage en Python. –

+3

Fournir plus de preuves. Le code du décorateur a l'air bien. Je ne crois pas votre affirmation ... –

Répondre

5

j'ai vu votre code collé - sur le pastebin. Le problème est que vous encapsulez la méthode __iter__ d'une classe. Il n'est appelé qu'une seule fois pour chaque boucle démarrée. Et il devrait revenir immédiatement avec un objet itérateur - ce qui serait profilable est les appels à la méthode "next" sur l'objet retourné par __iter__ (c'est ce qu'on appelle dans chaque for loop interacton).

Ce qui signifie que, sans changer quoi que ce soit, au lieu d'utiliser votre profileur comme décorateur sur un appel à __iter__ vous utiliseriez ce code dans une autre autour de la déclaration yield à l'intérieur taht __iter__

Autre que cela, vous sera préférable d'utiliser timeit.timeit ou d'autres profils déjà existants pour éviter de tels pièges, comme indiqué dans les commentaires.

Questions connexes