Comprensión de las comprensiones de lista en Python 3

Introducción

Las comprensiones de lista ofrecen una forma sucinta de crear listas basadas en listas existentes. Cuando se usan comprensiones de lista, las listas pueden construirse aprovechando cualquier iterable, incluyendo cadenas y tuplas.

Sintácticamente, las comprensiones de lista consisten en un iterable que contiene una expresión seguida de una cláusula for. Esto puede ir seguido de cláusulas adicionales for o if, por lo que familiarizarse con los bucles for y las sentencias condicionales te ayudará a entender mejor las comprensiones de lista.

Las comprensiones de listas proporcionan una sintaxis alternativa para crear listas y otros tipos de datos secuenciales. Si bien otros métodos de iteración, como los bucles `for`, también se pueden usar para crear listas, las comprensiones de listas pueden ser preferidas porque pueden limitar el número de líneas utilizadas en tu programa.

Requisitos previos

Debes tener instalado Python 3 y configurado un entorno de programación en tu computadora o servidor. Si no tienes configurado un entorno de programación, puedes consultar las guías de instalación y configuración para un entorno de programación local o para un entorno de programación en tu servidor adecuado para tu sistema operativo (Ubuntu, CentOS, Debian, etc.).

Comprensiones de Listas

En Python, las comprensiones de listas se construyen de la siguiente manera:

Información: Para seguir el código de ejemplo en este tutorial, abre un shell interactivo de Python en tu sistema local ejecutando el comando python3. Luego puedes copiar, pegar o editar los ejemplos agregándolos después del indicador >>>.

list_variable = [x for x in iterable]

A list, or other iterable, is assigned to a variable. Additional variables that stand for items within the iterable are constructed around a for clause. The in keyword is used as it is in for loops, to iterate over the iterable.

Veamos un ejemplo que crea una lista basada en una cadena:

shark_letters = [letter for letter in 'shark']
print(shark_letters)

Aquí, la nueva lista se asigna a la variable shark_letters, y letter se utiliza para representar los elementos contenidos en la cadena iterable 'shark'.

Para confirmar cómo se ve la nueva lista shark_letters, la imprimimos y obtenemos la siguiente salida:

Output
['s', 'h', 'a', 'r', 'k']

La lista que creamos con la comprensión de lista está compuesta por los elementos en la cadena 'shark', es decir, una cadena para cada letra.

Las comprensiones de lista pueden reescribirse como bucles for, aunque no todos los bucles for pueden reescribirse como una comprensión de lista.

Usando nuestra comprensión de lista que creó la lista shark_letters anteriormente, vamos a reescribirla como un bucle for. Esto puede ayudarnos a entender mejor cómo funciona la comprensión de lista.

shark_letters = []

for letter in 'shark':
    shark_letters.append(letter)

print(shark_letters)

Al crear una lista con un bucle for, la variable asignada a la lista necesita inicializarse con una lista vacía, como se hace en la primera línea de nuestro bloque de código. El bucle for luego itera sobre el ítem, utilizando la variable letter en la cadena iterable 'shark'. Dentro del bucle for, cada ítem dentro de la cadena se añade a la lista con el método list.append(x).

Reescribir la comprensión de lista como un bucle for nos proporciona el mismo resultado:

Output
['s', 'h', 'a', 'r', 'k']

Las comprensiones de lista pueden reescribirse como bucles for, y algunos bucles for pueden reescribirse como comprensiones de lista para hacer el código más sucinto.

Uso de condicionales con comprensiones de lista

Las comprensiones de lista pueden utilizar declaraciones condicionales para modificar listas existentes u otros tipos de datos secuenciales al crear nuevas listas.

Vamos a ver un ejemplo de una declaración if usada en una comprensión de lista:

fish_tuple = ('blowfish', 'clownfish', 'catfish', 'octopus')

fish_list = [fish for fish in fish_tuple if fish != 'octopus']
print(fish_list)

La comprensión de listas utiliza la tupla fish_tuple como base para la nueva lista llamada fish_list. Se utilizan las palabras clave for y in, como se hizo en la sección anterior, y ahora se agrega una declaración if. La declaración if indica que solo se añadan aquellos elementos que no sean equivalentes a la cadena 'octopus', por lo que la nueva lista solo incluye elementos de la tupla que no coinciden con 'octopus'.

Cuando ejecutamos esto, notaremos que fish_list contiene los mismos elementos de cadena que fish_tuple excepto por el hecho de que la cadena 'octopus' ha sido omitida:

Output
['blowfish', 'clownfish', 'catfish']

Por lo tanto, nuestra nueva lista tiene cada elemento de la tupla original excepto por la cadena que es excluida por la declaración condicional.

Crearemos otro ejemplo que utilice operadores matemáticos, enteros, y el tipo de secuencia range().

number_list = [x ** 2 for x in range(10) if x % 2 == 0]
print(number_list)

La lista que se está creando, number_list, se llenará con los valores al cuadrado de cada elemento en el rango de 0 a 9 si el valor del elemento es divisible por 2. El resultado es el siguiente:

Output
[0, 4, 16, 36, 64]

Para desglosar un poco más lo que hace la comprensión de lista, pensemos en lo que se imprimiría si solo estuviéramos llamando x for x in range(10). Nuestro pequeño programa y su salida se verían así:

number_list = [x for x in range(10)]
print(number_list)
Output
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Ahora, agreguemos la declaración condicional:

number_list = [x for x in range(10) if x % 2 == 0]
print(number_list)
Output
[0, 2, 4, 6, 8]

La declaración if ha limitado los elementos en la lista final para incluir solo aquellos que son divisibles por 2, omitiendo todos los números impares.

Finalmente, podemos agregar el operador para elevar al cuadrado cada x:

number_list = [x ** 2 for x in range(10) if x % 2 == 0]
print(number_list)

Entonces, cada uno de los números en la lista anterior de [0, 2, 4, 6, 8] ahora está elevado al cuadrado:

Output
[0, 4, 16, 36, 64]

También se pueden replicar declaraciones if anidadas con una comprensión de lista:

number_list = [x for x in range(100) if x % 3 == 0 if x % 5 == 0]
print(number_list)

Aquí, la comprensión de lista primero verificará si el número x es divisible por 3, y luego verificará si x es divisible por 5. Si x satisface ambos requisitos, se imprimirá, y la salida es:

Output
[0, 15, 30, 45, 60, 75, 90]

Las declaraciones condicionales if se pueden usar para controlar qué elementos de una secuencia existente se incluyen en la creación de una nueva lista.

Bucles Anidados en una Comprensión de Lista

Los bucles anidados se pueden usar para realizar múltiples iteraciones en nuestros programas.

Esta vez, revisaremos una construcción existente de bucles for anidados y avanzaremos hacia una comprensión de listas.

Nuestro código creará una nueva lista que itera sobre 2 listas y realiza operaciones matemáticas basadas en ellas. Aquí está nuestro bloque de código de bucle for anidado:

my_list = []

for x in [20, 40, 60]:
	for y in [2, 4, 6]:
		my_list.append(x * y)

print(my_list)

Cuando ejecutamos este código, recibimos la siguiente salida:

Output
[40, 80, 120, 80, 160, 240, 120, 240, 360]

Este código multiplica los elementos en la primera lista por los elementos en la segunda lista en cada iteración.

Para transformar esto en una comprensión de lista, condensaremos cada una de las líneas de código en una sola línea, comenzando con la operación x * y. Esto será seguido por el bucle for externo, luego el bucle for interno. Añadiremos una declaración print() debajo de nuestra comprensión de lista para confirmar que la nueva lista coincide con la lista que creamos con nuestro bloque de bucles for anidados anterior:

my_list = [x * y for x in [20, 40, 60] for y in [2, 4, 6]]
print(my_list)
Output
[40, 80, 120, 80, 160, 240, 120, 240, 360]

Nuestra comprensión de lista toma los bucles for anidados y los aplana en una sola línea de código mientras sigue creando la misma lista exacta para asignar a la variable my_list.

Las comprensiones de lista nos proporcionan una forma sucinta de crear listas, lo que nos permite destilar varias líneas de código en una sola línea. Sin embargo, vale la pena tener en cuenta que la legibilidad de nuestro código siempre debe tener prioridad, por lo que cuando una línea de comprensión de lista se vuelve demasiado larga o difícil de manejar, puede ser mejor desglosarla en bucles.

Conclusión

Las comprensiones de lista nos permiten transformar una lista u otra secuencia en una nueva lista. Proporcionan una sintaxis concisa para completar esta tarea, limitando nuestras líneas de código.

Las comprensiones de lista siguen la forma matemática de la notación de construcción de conjuntos o comprensión de conjuntos, por lo que pueden ser particularmente intuitivas para los programadores con formación matemática.

Aunque las comprensiones de lista pueden hacer que nuestro código sea más sucinto, es importante asegurarse de que nuestro código final sea lo más legible posible, por lo que se deben evitar líneas de código individuales muy largas para garantizar que nuestro código sea amigable para el usuario.

Source:
https://www.digitalocean.com/community/tutorials/understanding-list-comprehensions-in-python-3