Entries Tagged as 'programmation'

Calculer le temps mis pour une expression en python

Dans le langage clojure est présente une fonction bien pratique : time. Elle est similaire au time de bash.
Cette fonction bien pratique n’est pas présente dans la plupart des langages, alors qu’elle peut être fort utile.

user=> (time (* 6 7))
"Elapsed time: 0.07012 msecs"
42

Nous allons donc écrire une telle fonction pour python.

Il est évident que nous avons besoin d’importer le module time.
La manière de calculer le temps est plus que simple :

  • On récupère le temps avant l’évaluation du code
  • On évalue le code
  • On récupère le temps après l’évaluation
    Le temps pris par le code sera la différence entre le premier
    temps

La difficulté réside dans la façon d’appeler la fonction à évaluer. En effet, alors que les langages dérivés du lisp (dont
clojure fait partie) possèdent un système de macro puissant, python n’a pas de telle fonctionnalité. Nous ne pouvons donc pas appeler notre fonction time comme tel :

time(f(foo, bar))

Alors qu’en scheme par exemple, grâce aux macros on peut (code compatible avec guile uniquement, à cause de l’utilisation de la fonction current-time):

"Elapsed time : "" s"

Heureusement, python nous permet d’utiliser des fonctions à paramètre multiples, ainsi que d’appeler une fonction avec ses paramètres donnés dans une liste, ce qui nous permet de définir une fonction time utilisable.

def f(*args):
  return args

et

>>> apply(lambda x,y: x * y, [10, 5])
50

Nous pouvons alors définir notre fonction time, en faisant bien attention à ne pas importer le module time tel quel, sinon en appelant time.time(), python pensera qu’on souhaite appeler notre fonction time et retournera une erreur.

import time as t
 
def time(f, *args):
  start = t.time()
  apply(f, list(args))
  return t.time() - start

Et nous utiliserons notre fonction time comme suit :

>>> time(t.sleep, 10)
10.037008047103882
>>> time(lambda x, y: x * y, 6, 7)
2.002716064453125e-05

Le nombre retourné est le nombre de secondes qu’à duré l’exécution de l’appel de la fonction.

Nous pouvons aussi plus suivre ce que fait la fonction time de clojure via une définition comme cela :

def time(f, *args):
  start = t.time()
  res = apply(f, list(args))
  print "Elapsed time: ", (t.time() - start)*1000, " msecs"
  return res

Et le résultat :

>>> time(lambda x, y: x * y, 6, 7)
Elapsed time0.0240802764893  msecs
42
>>> time(t.sleep, 2)
Elapsed time2010.07699966  msecs

Sinon, il existe aussi le module timeit qui nous permet aussi de faire cela (mais de manière assez moche je trouve)