comprehensions-en-python

Cómo usar Comprensiones en Python

Introducción

En Python, la “comprensión” (o comprehension en inglés) se refiere a una sintaxis concisa para crear nuevas secuencias a partir de iterables existentes.

Pueden aplicarse a cualquier iterable, lo que incluye listas, conjuntos y diccionarios, entre otros. Pero también funcionará su creamos nuestros propios iterables.

Las comprensiones no solo son más concisas en sintaxis si no que, en ocasiones, también pueden ser más rápidas que las construcciones equivalentes usando bucles for.

La sintaxis básica,

expresion for elemento in iterable

Opcionalmente, podemos pasar una condición de filtro así

expresion for elemento in iterable if condicion

Siendo,

  • expresion: Es la parte que define el resultado de la comprension. Es una operación que genera el elemento final a partir del original.
  • for elemento in iterable: Este es el bucle que itera sobre cada elemento del iterable original
  • if condicion: Esta es una condición opcional que filtra los elementos del iterable original, antes de aplicarles la expresion.

Esta sintaxis tiene variaciones mínimas en función del objeto que queramos general con la compresión (ggneralmente variará en si envolveremos entre [] o {})

Pero mejor, vamos a verlo con unos ejemplos 👇

Comprensiones de Listas

Las comprensiones de listas permiten crear nuevas listas aplicando una expresión a cada elemento de una secuencia. La sintaxis básica es:

[expresion for elemento in iterable if condicion]

Por ejemplo, podemos aplicarlo sin condición

# Crear una lista de cuadrados de números del 0 al 9
cuadrados = [x**2 for x in range(10)]

print(cuadrados)  # Salida: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

O en este ejemplo con una condición,

# Crear una lista de cuadrados de los numeros 0 al 9 que son pares
cuadrados_pares = [x**2 for x in range(10) if x % 2 == 0]

print(cuadrados_pares)  # Salida: [0, 4, 16, 36, 64]

Comprensiones Anidadas

Las comprensiones de listas también pueden ser anidadas, lo que es útil para trabajar con estructuras multidimensionales.

# Crear una matriz identidad de 3x3
matriz_identidad = [[1 if i == j else 0 for j in range(3)] for i in range(3)]

print(matriz_identidad)
# Salida: [[1, 0, 0], [0, 1, 0], [0, 0, 1]]

En este ejemplo,

  • El [[...] for i in range(3)] exterior, genera 3 compresiones de lista
  • El [1 if i == j else 0 for j in range(3)] interior genera una lista que tiene 3 elementos, que son 1 si i==j.

Comprensiones de Conjuntos

Las comprensiones de conjuntos son similares a las de listas, pero generan un set. La sintaxis es:

{expresión for elemento in iterable if condición}

Por ejemplo,

# Crear un conjunto de números impares del 0 al 9
impares = {x for x in range(10) if x % 2 != 0}

print(impares)  # Salida: {1, 3, 5, 7, 9}

Comprensiones de Diccionarios

También podemos usar compresiones que nos permiten construir diccionarios de manera concisa. La sintaxis es:

{clave: valor for elemento in iterable if condición}

Por ejemplo, sin condición,

# Crear un diccionario con números y sus cuadrados para números del 0 al 9
cuadrados_dict = {x: x**2 for x in range(10)}

print(cuadrados_dict)
# Salida: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

O con una condición,

# Crear un diccionario de cuadrados solo para números pares del 0 al 9
cuadrados_pares_dict = {x: x**2 for x in range(10) if x % 2 == 0}

print(cuadrados_pares_dict)
# Salida: {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}

Comprensiones de Generadores

Los generadores retornan un objeto que produce elementos. La sintaxis es:

(expresion for elemento in iterable if condicion)

Por ejemplo,

# Crear un generador de cuadrados de números del 0 al 9
cuadrados_gen = (x**2 for x in range(10))

print(list(cuadrados_gen))  # Salida: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Puede parecer similar al caso de una lista, pero en este caso lo que tenemos es un iterable de generadores.

Esto sería útil si trabajamos con grande volúmenes de datos, que no necesitamos generar y cargar en memoria a la vez.

Es decir, en el ejemplo de la lista, cuadrados tenía calculados todos los valores. Embargo en el caso de cuadrados_gen se calcula una única vez cada vez que iteramos sobre la colección.

En el ejemplo parece similares, porque print(list()) recorre todos los elementos y los imprime.