Usando Python Timeit para cronometrar su código

En este tutorial, aprenderá a usar la función timeit del módulo timeit de Python. Aprenderá a cronometrar expresiones y funciones simples en Python.

La sincronización de su código puede ayudarlo a obtener una estimación del tiempo de ejecución de una parte del código y también a identificar las secciones del código que deben optimizarse.

Comenzaremos aprendiendo la sintaxis de la función timeit de Python. Y luego codificaremos ejemplos para comprender cómo usarlo para cronometrar bloques de código y funciones en su módulo de Python. Vamos a empezar.

Cómo usar la función timeit de Python

El módulo timeit es parte de la biblioteca estándar de Python y puede importarlo:

import timeit

La sintaxis para usar la función timeit del módulo timeit es la siguiente:

timeit.timeit(stmt, setup, number)

Aquí:

  • stmt es la pieza de código cuyo tiempo de ejecución se va a medir. Puede especificarlo como una cadena de Python simple o una cadena de varias líneas, o pasar el nombre del invocable.
  • Como sugiere el nombre, la configuración denota la pieza de código que debe ejecutarse solo una vez, a menudo como un requisito previo para que se ejecute la stmt. Por ejemplo, suponga que está calculando el tiempo de ejecución para la creación de una matriz NumPy. En este caso, importar numpy es el código de configuración y la creación real es la declaración que se cronometrará.
  • El número de parámetro indica el número de veces que se ejecuta la sentencia. El valor predeterminado de número es 1 millón (1000000), pero también puede establecer este parámetro en cualquier otro valor de su elección.

Ahora que hemos aprendido la sintaxis para usar la función timeit(), comencemos a codificar algunos ejemplos.

Temporización de expresiones simples de Python

En esta sección, intentaremos medir el tiempo de ejecución de expresiones simples de Python usando timeit.

Inicie un REPL de Python y ejecute los siguientes ejemplos de código. Aquí, estamos calculando el tiempo de ejecución de las operaciones de exponenciación y división de piso para 10000 y 100000 ejecuciones.

Observe que pasamos la declaración para que se cronometre como una cadena de Python y usamos un punto y coma para separar las diferentes expresiones en la declaración.

>>> import timeit
>>> timeit.timeit('3**4;3//4',number=10000)
0.0004020999999738706

>>> timeit.timeit('3**4;3//4',number=100000)
0.0013780000000451764

Ejecutando Python timeit en la línea de comando

También puede usar timeit en la línea de comandos. Aquí está el equivalente en la línea de comandos de la llamada a la función timeit:

$ python-m timeit -n [number] -s [setup] [stmt]
  • python -m timeit representa que ejecutamos timeit como el módulo principal.
  • n es una opción de línea de comandos que indica la cantidad de veces que se debe ejecutar el código. Esto es equivalente al argumento numérico en la llamada a la función timeit().
  • Puede usar la opción -s para definir el código de configuración.

Aquí, reescribimos el ejemplo anterior usando el equivalente de la línea de comandos:

$ python -m timeit -n 100000 '3**4;3//4'
100000 loops, best of 5: 35.8 nsec per loop

En este ejemplo, calculamos el tiempo de ejecución de la función integrada len(). La inicialización de la cadena es el código de configuración que se pasa usando la opción s.

$ python -m timeit -n 100000 -s "string_1 = 'coding'" 'len(string_1)'
100000 loops, best of 5: 239 nsec per loop

En la salida, observe que obtenemos el tiempo de ejecución al mejor de 5 ejecuciones. ¿Qué significa esto? Cuando ejecuta timeit en la línea de comando, la opción de repetición r se establece en el valor predeterminado de 5. Esto significa que la ejecución de la instrucción para el número especificado de veces se repite cinco veces y se devuelve el mejor de los tiempos de ejecución.

Análisis de métodos de inversión de cadenas usando timeit

Cuando trabaje con cadenas de Python, es posible que desee invertirlas. Los dos enfoques más comunes para la inversión de cadenas son los siguientes:

  • Usando el corte de cuerdas
  • Usando la función invertida() y el método join()

Cuerdas de Python inversas mediante el corte de cadenas

Repasemos cómo funciona el corte de cadenas y cómo puede usarlo para invertir una cadena de Python. Usando la sintaxis alguna cadena[start:stop] devuelve una porción de la cadena que comienza en el inicio del índice y se extiende hasta la parada del índice-1. Tomemos un ejemplo.

Considere la siguiente cadena ‘Python’. La cadena tiene una longitud de 6 y la lista de índices es 0, 1, 2 hasta 5.

>>> string_1 = 'Python'

Cuando especifica los valores de inicio y finalización, obtiene un segmento de cadena que se extiende desde el inicio hasta la finalización-1. Por lo tanto, cadena_1[1:4] devuelve ‘yth’.

>>> string_1 = 'Python'
>>> string_1[1:4]
'yth'

Cuando no especifica el valor de inicio, se usa el valor de inicio predeterminado de cero, y el segmento comienza en el índice cero y se extiende hasta detenerse: 1.

Aquí, el valor de parada es 3, por lo que el segmento comienza en el índice 0 y sube hasta el índice 2.

>>> string_1[:3]
'Pyt'

Cuando no incluye el índice de parada, verá que el segmento comienza desde el índice de inicio (1) y se extiende hasta el final de la cadena.

>>> string_1[1:]
'ython'

Ignorar los valores de inicio y finalización devuelve una porción de la cadena completa.

>>> string_1[::]
'Python'

Vamos a crear una rebanada con el valor del paso. Establezca los valores de inicio, parada y paso en 1, 5 y 2, respectivamente. Obtenemos una porción de la cadena que comienza en 1 y se extiende hasta 4 (excluyendo el punto final 5) que contiene cada segundo carácter.

>>> string_1[1:5:2]
'yh'

Cuando usa un paso negativo, puede obtener un segmento que comienza al final de la cadena. Con el paso establecido en -2, string_1[5:2:-2] da la siguiente rebanada:

>>> string_1[5:2:-2]
'nh'

Entonces, para obtener una copia invertida de la cadena, omitimos los valores de inicio y finalización y establecemos el paso en -1, como se muestra:

>>> string_1[::-1]
'nohtyP'

En resumen: cadena[::-1] devuelve una copia invertida de la cadena.

Inversión de cadenas mediante funciones integradas y métodos de cadena

La función invertida() incorporada en Python devolverá un iterador inverso sobre los elementos de la cadena.

>>> string_1 = 'Python'
>>> reversed(string_1)
<reversed object at 0x00BEAF70>

Entonces puede recorrer el iterador inverso usando un bucle for:

for char in reversed(string_1):
    print(char)

Y accede a los elementos de la cadena en el orden inverso.

# Output
n
o
h
t
y
P

A continuación, puede llamar al método join() en el iterador inverso con la sintaxis: .join(reversed(some-string)).

El fragmento de código siguiente muestra un par de ejemplos en los que el separador es un guión y un espacio en blanco, respectivamente.

>>> '-'.join(reversed(string1))
'n-o-h-t-y-P'
>>> ' '.join(reversed(string1))
'n o h t y P'

Aquí, no queremos ningún separador; así que establezca el separador en una cadena vacía para obtener una copia invertida de la cadena:

>>> ''.join(reversed(string1))
'nohtyP'

El uso de ”.join(reversed(some-string)) devuelve una copia invertida de la cadena.

Comparación de tiempos de ejecución usando timeit

Hasta ahora, hemos aprendido dos enfoques para invertir cadenas de Python. Pero, ¿cuál de ellos es más rápido? Vamos a averiguar.

En un ejemplo anterior en el que cronometramos expresiones simples de Python, no teníamos ningún código de configuración. Aquí, estamos invirtiendo la cadena de Python. Si bien la operación de inversión de la cadena se ejecuta la cantidad de veces especificada por el número, el código de configuración es la inicialización de la cadena que se ejecutará solo una vez.

>>> import timeit
>>> timeit.timeit(stmt="string_1[::-1]", setup = "string_1 = 'Python'", number = 100000)
0.04951830000001678
>>> timeit.timeit(stmt = "''.join(reversed(string_1))", setup = "string_1 = 'Python'", number = 100000)
0.12858760000000302

Para el mismo número de ejecuciones para invertir la cadena dada, el enfoque de división de cadenas es más rápido que usar el método join() y la función reversed().

Temporización de funciones de Python usando timeit

En esta sección, aprendamos cómo cronometrar las funciones de Python con la función timeit. Dada una lista de cadenas, la siguiente función hasDigit devuelve la lista de cadenas que tienen al menos un dígito.

def hasDigit(somelist):
     str_with_digit = []
     for string in somelist:
         check_char = [char.isdigit() for char in string]
         if any(check_char):
            str_with_digit.append(string)
     return str_with_digit

Ahora nos gustaría medir el tiempo de ejecución de esta función de Python hasDigit() usando timeit.

Primero identifiquemos la sentencia a cronometrar (stmt). Es la llamada a la función hasDigit() con una lista de cadenas como argumento. A continuación, definamos el código de configuración. ¿Puedes adivinar cuál debería ser el código de configuración?

Para que la llamada a la función se ejecute correctamente, el código de configuración debe incluir lo siguiente:

  • La definición de la función hasDigit()
  • La inicialización de la lista de argumentos de cadenas.

Definamos el código de configuración en la cadena de configuración, como se muestra a continuación:

setup = """
def hasDigit(somelist):
    str_with_digit = []
    for string in somelist:
      check_char = [char.isdigit() for char in string]
      if any(check_char):
        str_with_digit.append(string)
    return str_with_digit
thislist=['puffin3','7frost','blue']
     """

A continuación, podemos usar la función timeit y obtener el tiempo de ejecución de la función hasDigit() para 100000 ejecuciones.

import timeit
timeit.timeit('hasDigit(thislist)',setup=setup,number=100000)
# Output
0.2810094920000097

Conclusión

Aprendió a usar la función timeit de Python para cronometrar expresiones, funciones y otras llamadas. Esto puede ayudarlo a comparar su código, comparar los tiempos de ejecución de diferentes implementaciones de la misma función y más.

Repasemos lo que hemos aprendido en este tutorial. Puede usar la función timeit() con la sintaxis timeit.timeit(stmt=…,setup=…,number=…). Alternativamente, puede ejecutar timeit en la línea de comando para cronometrar fragmentos de código cortos.

Como siguiente paso, puede explorar cómo usar otros paquetes de generación de perfiles de Python, como line-profiler y memprofiler, para generar un perfil de tiempo y memoria de su código, respectivamente.

A continuación, aprenda a calcular la diferencia horaria en Python.