Comprensiones de Python: Introducción paso a paso - Hoja de trucos de Python

List Comprehensions son un tipo especial de sintaxis que nos permite crear listas a partir de otras listas (Wikipedia, The Python Tutorial). Son increíblemente útiles cuando se trabaja con números y con uno o dos niveles de for loops anidados, pero más allá de eso, pueden volverse un poco difíciles de leer.
En este artículo, vamos a crear algunos For Loops y reescribirlos, paso a paso, en Comprehensions.
Conceptos básicos
La verdad es que las List Comprehensions no son demasiado complejas, pero siguen siendo un poco difíciles de entender al principio porque se ven un poco raras. ¿Por qué? Bueno, el orden en que están escritas es el opuesto a lo que solemos ver en un For Loop.
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> for n in names:
... print(n)
# Charles
# Susan
# Patrick
# George
# Carol
Para hacer lo mismo con una List Comprehension, comenzamos al final del loop:
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> [print(n) for n in names]
# Charles
# Susan
# Patrick
# George
# Carol
Observa cómo invertimos el orden:
- Primero, tenemos lo que será la salida del bucle
[print(n) ...]. - Luego definimos la variable que almacenará cada uno de los elementos y apuntamos a la
List,SetoDictionarycon la que trabajaremos[... for n in names].
Crear una nueva lista con una comprensión
Este es el uso principal de una List Comprehension. Otros usos pueden resultar en un código difícil de leer para ti y para otros.
Así es como creamos una nueva lista a partir de una colección existente con un For Loop:
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> new_list = []
>>> for n in names:
... new_list.append(n)
>>> print(new_list)
# ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
Y así es como hacemos lo mismo con una List Comprehension:
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> new_list = [n for n in names]
>>> print(new_list)
# ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
La razón por la que podemos hacer esto es que el comportamiento estándar de una List Comprehension es devolver una lista:
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> [n for n in names]
# ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
Agregar condicionales
¿Qué pasa si queremos que new_list solo contenga los nombres que comienzan con C? Con un For Loop, lo haríamos así:
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> new_list = []
>>> for n in names:
... if n.startswith('C'):
... new_list.append(n)
>>> print(new_list)
# ['Charles', 'Carol']
En una List Comprehension, añadimos la sentencia if al final:
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> new_list = [n for n in names if n.startswith('C')]
>>> print(new_list)
# ['Charles', 'Carol']
Mucho más legible.
Dar formato a comprensiones de lista largas
Esta vez, queremos que new_list contenga no solo los nombres que comienzan con C, sino también aquellos que terminan en e y contienen una k:
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> new_list = [n for n in names if n.startswith('C') or n.endswith('e') or 'k' in n]
>>> print(new_list)
# ['Charles', 'Patrick', 'George', 'Carol']
Eso es bastante desordenado. Afortunadamente, es posible dividir las Comprehensions en diferentes líneas:
new_list = [
n
for n in names
if n.startswith("C")
or n.endswith("e")
or "k" in n
]
Comprensiones de set y dict
Si aprendiste los conceptos básicos de las List Comprehensions… ¡Felicidades! Acabas de hacerlo con Sets y Dictionaries.
Comprensión de set
>>> my_set = {"abc", "def"}
>>> # Aquí, creamos un nuevo set con elementos en mayúsculas con un bucle for
>>> new_set = set()
>>> for s in my_set:
... new_set.add(s.upper())
>>> print(new_set)
# {'DEF', 'ABC'}
>>> # Lo mismo, pero con una set comprehension
>>> new_set = {s.upper() for s in my_set}
>>> print(new_set)
# {'DEF', 'ABC'}
Comprensión de dict
>>> my_dict = {'name': 'Christine', 'age': 98}
>>> # Un nuevo diccionario a partir de uno existente con un bucle for
>>> new_dict = {}
>>> for key, value in my_dict.items():
... new_dict[key] = value
>>> print(new_dict)
# {'name': 'Christine', 'age': 98}
# Usando una dict comprehension
>>> new_dict = {key: value for key, value in my_dict.items()} # Notice the ":"
>>> print(new_dict)
# {'name': 'Christine', 'age': 98}
Artículo recomendado: Python Sets: What, Why and How .
Conclusión
Cada vez que aprendo algo nuevo, surge esta urgencia de usarlo de inmediato. Cuando eso sucede, me obligo a detenerme y pensar por un momento… ¿Debería cambiar este For Loop grande, anidado y que ya se ve desordenado a una List Comprehension? Probablemente no.
Readability counts. The Zen of Python.