Bucles en Python

B

Elección de la estructura de bucle adecuada

Python ofrece una variedad de construcciones para hacer bucles. Este artículo los presenta y brinda consejos sobre su uso específico. Además, también veremos el rendimiento de cada construcción de bucle en su código Python. Puede que te sorprenda.

Bucles, bucles, bucles

Un lenguaje de programación normalmente consta de varios tipos de elementos básicos, como asignaciones, declaraciones y bucles. La idea detrás de un bucle es repetir acciones individuales que se indican en el cuerpo del bucle. Son comunes diferentes tipos de bucles:

  • siempre que una condición especificada sea verdadera (mientras que la condición haga algo).
  • hasta que se cumpla una determinada condición (hacer algo hasta la condición)
  • para un número fijo de pasos (iteraciones) (para / de ‘x’ a ‘y’ hacer algo).
  • bucle sin fin y salida / interrupción en condición (mientras que condición1 hace algo y sale en condición2)

Construcciones de bucle compatibles con Python

Python admite un número parcial de las construcciones mencionadas anteriormente, además ofrece extensiones únicas para los tipos que hemos mencionado.

Básico while Bucles

while condition:
    statements

Siempre y cuando la “condición” se cumpla con todas las declaraciones en el cuerpo del while bucle se ejecutan al menos una vez. Después de cada vez que se ejecutan las declaraciones, se vuelve a evaluar la condición. Escribir un bucle se ve así:

Listado 1

fruits = ["banana", "apple", "orange", "kiwi"]
position = 0
while position < len(fruits):
    print(fruits[position])
    position = position + 1
print("reached end of list")

Este código generará un elemento de lista después del siguiente:

banana
apple
orange
kiwi
reached end of list

while Bucles con else Cláusula

Esta construcción es específica del lenguaje Python, pero muy útil:

while condition:
    statements
else:
    statements

Esta while El bucle actúa de manera similar al regular. while bucle como se introdujo antes. Las declaraciones en el else part se ejecutan tan pronto como la condición deja de ser cierta. Por ejemplo, en caso de que se llegue al final de una lista, como en nuestro ejemplo anterior. Puede interpretarlo como then si la condición del bucle ya no se cumple.

Listado 2

fruits = ["banana", "apple", "orange", "kiwi"]
position = 0
while position < len(fruits):
    print(fruits[position])
    position = position + 1
else:
    print("reached end of list")

Esto generará un elemento de lista tras el siguiente, más el texto adicional del print declaración en la cláusula else:

banana
apple
orange
kiwi
reached end of list

Este tipo de bucle con un else La cláusula es útil para enviar mensajes o ejecutar declaraciones en caso de que su condición falle.

Una cosa importante a tener en cuenta es que el else la cláusula no se ejecuta si break fuera de while bucle o si se lanza un error desde dentro del while lazo.

Infinito while Bucles

Los bucles infinitos siempre se enseñan como componentes críticos y deben evitarse si la condición de rotura es un asunto complicado. Aunque hay casos en los que los bucles infinitos te ayudan a escribir código de forma elegante.

Estos son solo algunos casos de uso de bucles infinitos:

  • dispositivos que intentan mantener las conexiones de red activas como puntos de acceso inalámbricos
  • clientes que intentan intercambiar datos constantemente con un sistema host, como un sistema de archivos basado en red (NFS o Samba / CIFS)
  • bucles de juego para dibujar y actualizar el estado de tu juego
while True:
    if condition:
        break
    statements

Tenga en cuenta que las declaraciones en el cuerpo de un bucle sin fin se ejecutan al menos una vez. Es por eso que recomiendo escribir la condición de interrupción como la primera declaración después del encabezado del ciclo. Siguiendo nuestro código de ejemplo, un bucle infinito se ve como sigue:

Listado 3

fruits = ["banana", "apple", "orange", "kiwi"]
position = 0
while True:
    if position >= len(fruits):
        break
    print(fruits[position])
    position = position + 1
print("reached end of list")

for Bucles con un iterador

Trabajar con listas se describe como usar la palabra clave for en combinación con un iterador. El pseudocódigo tiene el siguiente aspecto:

for temp_var in sequence:
    statements

Esto simplifica el código Python para procesar nuestra lista de la siguiente manera:

Listado 4

fruits = ["banana", "apple", "orange", "kiwi"]
for food in fruits:
    print(food)
print("reached end of list")

En este tipo de construcción de bucle, el intérprete de Python maneja la iteración sobre la lista y se encarga de que el bucle no se ejecute fuera del rango de la lista. Tenga en cuenta que las declaraciones en el cuerpo del ciclo se ejecutan una vez para cada elemento de la lista, sin importar si es solo uno o veinte mil.

En caso de que la lista esté vacía, las declaraciones en el cuerpo del ciclo no se ejecutan. Cambiar la lista en términos de agregar o eliminar elementos dentro del for El bucle puede confundir al intérprete de Python y causar problemas, así que tenga cuidado.

for Bucles con iterador y else Cláusula

Similar a while bucle, Python también ofrece un else declaración para el for lazo. Funciona de manera similar y se puede interpretar como then, como antes. El pseudocódigo tiene el siguiente aspecto:

for temp_var in sequence:
    statements
else:
    statements

Usando esta palabra clave, nuestro código cambia de la siguiente manera:

Listado 5

fruits = ["banana", "apple", "orange", "kiwi"]
for food in fruits:
    print(food)
else:
    print("reached end of list")

Construcciones de bucle no admitidas

Como se indicó al principio, hay muchos estilos de bucle diferentes. Sin embargo, Python no los admite a todos. Python no es compatible con do-until bucle o un foreach loop, como posiblemente se conoce de PHP. Tales casos se resuelven usando Python in operador que crea un código bastante atractivo si se familiariza con él. Vea las formas alternativas de escribir un bucle desde arriba.

¿Qué bucle elegir?

En general el while condition Los bucles requieren que se especifique una condición antes de las declaraciones del bucle. Esto puede llevar al caso de que las declaraciones en el cuerpo del bucle nunca se ejecuten. Además, no siempre está claro cuántas veces se ejecutará el ciclo durante while bucles. En lugar, for los bucles se centran en el iterador que especifica la frecuencia con la que se ejecutan las instrucciones del cuerpo del bucle.

Se recomienda utilizar un for bucle si conoce exactamente el número de elementos sobre los que se iterará. En contraste, un while Loop es mejor cuando tienes una expresión booleana para evaluar, y no una lista de elementos para recorrer.

Mejorando la calidad de su código

Muchos programadores más jóvenes no siempre se preocupan por la calidad de su código, en gran parte porque han crecido en una época en la que nadie tiene que pensar en la memoria y la potencia de la CPU; simplemente tenemos mucho disponible en las computadoras modernas. En cambio, los desarrolladores más experimentados (también conocidos como “mayores”) son más propensos a optimizar su código tanto como sea posible y pueden recordar contar las instrucciones de la CPU y el número de celdas de memoria que están en uso.

Entonces, ¿qué significa calidad hoy? En términos de efectividad, cubre escribir la menor cantidad de código posible y ejecutar código de manera efectiva, solo tantas instrucciones de procesador como sea necesario. En primer lugar, con los intérpretes, los tiempos de ejecución y los marcos actuales es bastante difícil calcularlo correctamente y, en segundo lugar, siempre existe una compensación entre estas dos medidas. Las preguntas clave son, con qué frecuencia se utilizará este código y cuánto tiempo dedicaremos a optimizarlo para ganar unos microsegundos de tiempo de CPU.

Como ejemplo, veremos un for bucle iterando sobre una lista. Por lo general, lo escribimos de la siguiente manera:

Listado 6

for entry in range(0, 3):
    print(entry)

Esto genera los valores 0, 1 y 2. El range() método crea el iterable [0, 1, 2] cada vez que se evalúa la cabeza del bucle. Por tanto, es mejor escribirlo de la siguiente manera:

Listado 7

entryRange = range(0, 3)
for entry in entryRange:
    print(entry)

Si bien esto puede no parecer una gran optimización para el ejemplo dado, considere si el rango era de 0 a 1,000,000 o más. A medida que nuestra lista crece, ahorramos más tiempo y nuestro código se ejecuta más rápido.

Además, estas declaraciones se pueden expresar como while lazo:

Listado 8

entryRange = range(0, 3)
index = 0
while index < len(entryRange):
    print(entryRange[index])
    index = index + 1

Y en este punto parece un poco inútil incluso usar el range() función. En su lugar, también podríamos usar una constante para el condicional y index como contador para el condicional y la impresión:

index = 0
while index < 3:
    print(index)
    index = index + 1

Pequeñas optimizaciones como estas pueden proporcionar pequeñas mejoras de rendimiento para sus bucles, especialmente cuando el número de iteraciones se vuelve muy grande.

Pruebas de rendimiento

Hasta ahora hablamos sobre el código de bucle y cómo escribirlo correctamente. Una prueba de rendimiento puede ayudar a aclarar algo. La idea fue tomada de un interesante artículo de blog de Ned Batchelder. [1].

En uso es el perf herramienta que realiza pruebas de rendimiento para el código del programa que se ejecuta [2]. La llamada básica es perf stat program mientras stat abrevia estadística y programa es la llamada que nos gustaría evaluar. Para probar nuestras variantes de bucle se realizaron estas llamadas:

Listado 9

perf stat python3 while-1.py
perf stat python3 while-2.py
perf stat python3 while-3.py
perf stat python3 for-4.py
perf stat python3 for-5.py
perf stat python3 for-6.py
perf stat python3 for-7.py
perf stat python3 while-8.py

Estos resultados son el promedio basado en 10 ejecuciones debido a las diferencias de carga en el kernel de Linux. La siguiente tabla muestra los resultados:

Tema Listado 1 Listado 2 Listado 3 Listado 4 Listado 5

reloj de tareas (mseg)20.16007718.53526415.97538715.42733415.503672
cambios de contexto1011101310
migraciones de cpu00211
fallas de página851849855848851
ciclos41,915,01044,938,83744,403,69642,983,39242,489,206
instrucciones46,833,82046,803,18746,926,38346,596,66746,701,350

Para los listados 6 a 8 se ve como sigue:

Tema Listado 6 Listado 7 Listado 8

reloj de tareas (mseg)16.48032218.19343715.734627
cambios de contexto91111
migraciones de cpu001
fallas de página850851853
ciclos42,424,63942,569,55043,038,837
instrucciones46,703,89346,724,19046,695,710

Conclusión

Python ofrece diferentes formas de repetir acciones y escribir bucles de escritura. Hay variantes por caso de uso específico. Nuestras pruebas han demostrado que los bucles están en la misma dimensión con pequeñas diferencias y la optimización del intérprete de Python es bastante buena.

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias para su correcto funcionamiento. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad