2.3 Técnicas de Optimización en Algoritmos#
Una vez que un algoritmo funciona correctamente y comprendemos su complejidad computacional, el siguiente paso lógico es la optimización. Optimizar significa refactorizar el código para que consuma menos recursos (tiempo de procesamiento y memoria RAM) y sea más fácil de leer y mantener, sin alterar su resultado final.
A continuación, exploramos las técnicas fundamentales para lograr algoritmos más eficientes.
A. Principio DRY (Don’t Repeat Yourself)#
El principio «No te repitas» establece que ninguna pieza de lógica debería aparecer duplicada en el código. Si te encuentras copiando y pegando el mismo bloque de instrucciones múltiples veces, es momento de optimizar.
Solución: Agrupar la lógica repetitiva dentro de Ciclos o Funciones.
Beneficio: Si la regla de negocio cambia (por ejemplo, el impuesto pasa del 19% al 15%), solo debes modificar el código en un solo lugar, reduciendo drásticamente los errores de mantenimiento.
B. Salidas Tempranas (Early Exit / Break)#
Cuando realizamos búsquedas o validaciones dentro de un ciclo, no siempre es necesario recorrer todos los datos. Si ya encontramos la respuesta que buscábamos o detectamos un error que invalida el proceso, debemos detener la ejecución inmediatamente.
Uso del comando
break: Interrumpe un ciclo completo.Uso del comando
return(en funciones): Devuelve el resultado y sale del subprograma.
Ejemplo ineficiente: Un ciclo que revisa 10,000 facturas para ver si existe la factura #5. Si la encuentra en la posición 2, igual revisa las 9,998 restantes.
Ejemplo optimizado:
factura_buscada = 5
for factura in lista_facturas:
if factura['id'] == factura_buscada:
print("Factura encontrada")
break # Detiene el ciclo inmediatamente
C. Uso de Estructuras de Datos Eficientes (Sets)#
En la sección anterior vimos la superioridad de los diccionarios sobre las listas para búsquedas por clave. Otra estructura vital para la optimización en Python son los Conjuntos (Sets).
Características: Son colecciones desordenadas de elementos únicos. No permiten duplicados.
Ventaja Computacional: Al igual que los diccionarios, los conjuntos tienen una complejidad de tiempo \(O(1)\) para verificar si un elemento existe (membresía).
Aplicación: Si necesitas cruzar dos bases de datos enormes para ver qué clientes de la lista A también están en la lista B, convertir las listas a Sets hará que el proceso pase de tardar minutos a milisegundos.
# Búsqueda extremadamente rápida usando Sets
clientes_vip = {"Juan", "Ana", "Carlos"}
if "Ana" in clientes_vip: # Esta operación toma tiempo O(1)
print("Aplicar trato preferencial")
D. Comprensión de Listas (List Comprehensions)#
Esta es una técnica específica de Python que permite crear listas nuevas a partir de listas existentes de una manera mucho más concisa y rápida que usando un ciclo for tradicional. Python optimiza estas expresiones a nivel interno (en el lenguaje C subyacente), ejecutándolas a mayor velocidad.
Código Tradicional (Toma 3 líneas):
precios_con_iva = []
for precio in lista_precios:
precios_con_iva.append(precio * 1.19)
Código Optimizado (Toma 1 línea):
precios_con_iva = [precio * 1.19 for precio in lista_precios]