¿Cómo usar Python Timeit al pasar variables a funciones?

Estoy luchando con esto usando timeit y me preguntaba si alguien tenía algún consejo.

Básicamente tengo una función (a la que le paso un valor) para la cual quiero probar la velocidad y he creado esto:

if __name__=='__main__': from timeit import Timer t = Timer(superMegaIntenseFunction(10)) print t.timeit(number=1) 

pero cuando lo ejecuto, recibo errores extraños, como los provenientes del módulo timeit:

 ValueError: stmt is neither a string nor callable 

Si ejecuto la función por su cuenta, funciona bien. Es cuando lo envuelvo en el módulo de tiempo, recibo los errores (he intentado usar comillas dobles y sin … la misma salida).

Cualquier sugerencia sería increíble!

¡Gracias!

Hazlo un llamable

 if __name__=='__main__': from timeit import Timer t = Timer(lambda: superMegaIntenseFunction(10)) print(t.timeit(number=1)) 

Deberia trabajar

Timer(superMegaIntenseFunction(10)) significa “llamar a superMegaIntenseFunction(10) , luego pasar el resultado al Timer “. Eso claramente no es lo que quieres. Timer espera una llamada (como suena: algo que puede llamarse, como una función), o una cadena (para que pueda interpretar el contenido de la cadena como código Python). Timer funciona llamando repetidamente al objeto que se puede llamar y viendo cuánto tiempo se tarda.

Timer(superMegaIntenseFunction) pasaría la verificación de tipo, porque superMegaIntenseFunction es llamable. Sin embargo, Timer no sabría qué valores pasar a superMegaIntenseFunction .

La forma simple de evitar esto, por supuesto, es usar una cadena con el código. Necesitamos pasar un argumento de ‘configuración’ al código, porque la cadena se “interpreta como código” en un contexto nuevo; no tiene acceso a los mismos globals , por lo que debe ejecutar otro bit de código para que definición disponible – ver la respuesta de @xtopus.

Con lambda (como en la respuesta de @ Pablo), podemos vincular el parámetro 10 a una llamada a superMegaIntenseFunction . Todo lo que estamos haciendo es crear otra función, que no tiene argumentos, y llama a superMegaIntenseFunction con 10 . Es como si hubieras usado def para crear otra función así, excepto que la nueva función no recibe un nombre (porque no la necesita).

Deberías pasar una cadena. es decir

 t = Timer('superMegaIntenseFunction(10)','from __main__ import superMegaIntenseFunction') 

Una nota para futuros visitantes. Si necesita hacer que funcione en el depurador pdb , y superMegaIntenseFunction no está en el ámbito global, puede hacerlo funcionar agregando a los globals :

 globals()['superMegaIntenseFunction'] = superMegaIntenseFunction timeit.timeit(lambda: superMegaIntenseFunction(x)) 

Tenga en cuenta que la sobrecarga de tiempo es un poco mayor en este caso debido a las llamadas a funciones adicionales. [fuente]

Una forma de hacerlo sería usando parcial para que la función, ‘superMegaIntenseFunction’ se use como llamable (es decir, sin ()) en el temporizador o directamente dentro de timeit.timeit. El uso parcial pasará el argumento a la función cuando será llamado por el temporizador.

 from functools import partial from timeit import timeit print(timeit(partial(superMegaIntenseFunction, 10), number=1))