Introducción
Una tarea común es procesar elementos de una lista. En esta sección se presentan las comprensiones de lista, una herramienta poderosa para hacer precisamente eso.
This tutorial is from open-source community. Access the source code
Una tarea común es procesar elementos de una lista. En esta sección se presentan las comprensiones de lista, una herramienta poderosa para hacer precisamente eso.
Una comprensión de lista crea una nueva lista aplicando una operación a cada elemento de una secuencia.
>>> a = [1, 2, 3, 4, 5]
>>> b = [2*x for x in a ]
>>> b
[2, 4, 6, 8, 10]
>>>
Otro ejemplo:
>>> names = ['Elwood', 'Jake']
>>> a = [name.lower() for name in names]
>>> a
['elwood', 'jake']
>>>
La sintaxis general es: [ <expresión> for <nombre_variable> in <secuencia> ].
También puedes filtrar durante la comprensión de lista.
>>> a = [1, -5, 4, 2, -2, 10]
>>> b = [2*x for x in a if x > 0 ]
>>> b
[2, 8, 4, 20]
>>>
Las comprensiones de lista son muy útiles. Por ejemplo, puedes recopilar los valores de un campo específico de un diccionario:
stocknames = [s['name'] for s in stocks]
Puedes realizar consultas similares a las de una base de datos en secuencias.
a = [s for s in stocks if s['price'] > 100 and s['shares'] > 50 ]
También puedes combinar una comprensión de lista con una reducción de secuencia:
cost = sum([s['shares']*s['price'] for s in stocks])
[ <expresión> for <nombre_variable> in <secuencia> if <condición>]
Qué significa:
result = []
for nombre_variable in secuencia:
if condición:
result.append(expresión)
Las comprensiones de lista provienen de las matemáticas (notación de construcción de conjuntos).
a = [ x * x for x in s if x > 0 ] ## Python
a = { x^2 | x ∈ s, x > 0 } ## Matemáticas
También está implementada en varios otros lenguajes. Sin embargo, la mayoría de los programadores probablemente no están pensando en su clase de matemáticas. Entonces, está bien verla como un atajo de lista genial.
Prueba algunas comprensiones de lista simples solo para familiarizarte con la sintaxis.
>>> nums = [1,2,3,4]
>>> squares = [ x * x for x in nums ]
>>> squares
[1, 4, 9, 16]
>>> twice = [ 2 * x for x in nums if x > 2 ]
>>> twice
[6, 8]
>>>
Observa cómo las comprensiones de lista están creando una nueva lista con los datos adecuadamente transformados o filtrados.
Calcula el costo total de la cartera utilizando una sola instrucción de Python.
>>> portfolio = read_portfolio('portfolio.csv')
>>> cost = sum([ s['shares'] * s['price'] for s in portfolio ])
>>> cost
44671.15
>>>
Una vez que hayas hecho eso, muestra cómo puedes calcular el valor actual de la cartera utilizando una sola instrucción.
>>> value = sum([ s['shares'] * prices[s['name']] for s in portfolio ])
>>> value
28686.1
>>>
Ambas operaciones anteriores son un ejemplo de map-reduce. La comprensión de lista está aplicando una operación a través de la lista.
>>> [ s['shares'] * s['price'] for s in portfolio ]
[3220.0000000000005, 4555.0, 12516.0, 10246.0, 3835.1499999999996, 3254.9999999999995, 7044.0]
>>>
La función sum() luego está realizando una reducción en el resultado:
>>> sum(_)
44671.15
>>>
Con este conocimiento, ya estás listo para lanzar una empresa de startups de big data.
Prueba los siguientes ejemplos de diversas consultas de datos.
Primero, una lista de todas las posesiones de la cartera con más de 100 acciones.
>>> more100 = [ s for s in portfolio if s['shares'] > 100 ]
>>> more100
[{'price': 83.44, 'name': 'CAT','shares': 150}, {'price': 51.23, 'name': 'MSFT','shares': 200}]
>>>
Todas las posesiones de la cartera de las acciones de MSFT e IBM.
>>> msftibm = [ s for s in portfolio if s['name'] in {'MSFT','IBM'} ]
>>> msftibm
[{'price': 91.1, 'name': 'IBM','shares': 50}, {'price': 51.23, 'name': 'MSFT','shares': 200},
{'price': 65.1, 'name': 'MSFT','shares': 50}, {'price': 70.44, 'name': 'IBM','shares': 100}]
>>>
Una lista de todas las posesiones de la cartera que cuestan más de $10000.
>>> cost10k = [ s for s in portfolio if s['shares'] * s['price'] > 10000 ]
>>> cost10k
[{'price': 83.44, 'name': 'CAT','shares': 150}, {'price': 51.23, 'name': 'MSFT','shares': 200}]
>>>
Muestra cómo podrías construir una lista de tuplas (nombre, acciones) donde nombre y acciones se tomen de portfolio.
>>> name_shares =[ (s['name'], s['shares']) for s in portfolio ]
>>> name_shares
[('AA', 100), ('IBM', 50), ('CAT', 150), ('MSFT', 200), ('GE', 95), ('MSFT', 50), ('IBM', 100)]
>>>
Si cambias los corchetes ([, ]) por llaves ({, }), obtienes algo conocido como una comprensión de conjunto. Esto te da valores únicos o distintos.
Por ejemplo, esto determina el conjunto de nombres de acciones únicos que aparecen en portfolio:
>>> names = { s['name'] for s in portfolio }
>>> names
{ 'AA', 'GE', 'IBM', 'MSFT', 'CAT' }
>>>
Si especificas pares clave:valor, puedes construir un diccionario. Por ejemplo, crea un diccionario que asocie el nombre de una acción con el número total de acciones poseídas.
>>> holdings = { name: 0 for name in names }
>>> holdings
{'AA': 0, 'GE': 0, 'IBM': 0, 'MSFT': 0, 'CAT': 0}
>>>
Esta última característica se conoce como una comprensión de diccionario. Hagamos una tabla:
>>> for s in portfolio:
holdings[s['name']] += s['shares']
>>> holdings
{ 'AA': 100, 'GE': 95, 'IBM': 150, 'MSFT':250, 'CAT': 150 }
>>>
Prueba este ejemplo que filtra el diccionario prices solo a aquellos nombres que aparecen en la cartera:
>>> portfolio_prices = { name: prices[name] for name in names }
>>> portfolio_prices
{'AA': 9.22, 'GE': 13.48, 'IBM': 106.28, 'MSFT': 20.89, 'CAT': 35.46}
>>>
Saberse utilizar diversas combinaciones de comprensiones de lista, conjunto y diccionario puede ser útil en diversas formas de procesamiento de datos. Aquí hay un ejemplo que muestra cómo extraer columnas seleccionadas de un archivo CSV.
Primero, lee una fila de información de encabezado de un archivo CSV:
>>> import csv
>>> f = open('portfoliodate.csv')
>>> rows = csv.reader(f)
>>> headers = next(rows)
>>> headers
['name', 'date', 'time','shares', 'price']
>>>
Luego, define una variable que liste las columnas en las que realmente te interesa:
>>> select = ['name','shares', 'price']
>>>
Ahora, localiza los índices de las columnas anteriores en el archivo CSV de origen:
>>> indices = [ headers.index(colname) for colname in select ]
>>> indices
[0, 3, 4]
>>>
Finalmente, lee una fila de datos y conviértela en un diccionario utilizando una comprensión de diccionario:
>>> row = next(rows)
>>> record = { colname: row[index] for colname, index in zip(select, indices) } ## dict-comprehension
>>> record
{'price': '32.20', 'name': 'AA','shares': '100'}
>>>
Si te sientes cómodo con lo que acaba de suceder, lee el resto del archivo:
>>> portfolio = [ { colname: row[index] for colname, index in zip(select, indices) } for row in rows ]
>>> portfolio
[{'price': '91.10', 'name': 'IBM','shares': '50'}, {'price': '83.44', 'name': 'CAT','shares': '150'},
{'price': '51.23', 'name': 'MSFT','shares': '200'}, {'price': '40.37', 'name': 'GE','shares': '95'},
{'price': '65.10', 'name': 'MSFT','shares': '50'}, {'price': '70.44', 'name': 'IBM','shares': '100'}]
>>>
Oh, mira, acabas de reducir gran parte de la función read_portfolio() a una sola instrucción.
Las comprensiones de lista se utilizan comúnmente en Python como un medio eficiente para transformar, filtrar o recopilar datos. Debido a la sintaxis, no quieres exagerar, trata de mantener cada comprensión de lista lo más simple posible. Está bien dividir las cosas en pasos múltiples. Por ejemplo, no está claro que quieres sorprender a tus compañeros de trabajo con el último ejemplo sin previo aviso.
Dicho esto, saber manipular rápidamente los datos es una habilidad que es increíblemente útil. Hay numerosas situaciones en las que es posible que tengas que resolver algún tipo de problema único que involucre importaciones, exportaciones, extracciones de datos, etc. Convertirse en un maestro guru de las comprensiones de lista puede reducir sustancialmente el tiempo invertido en idear una solución. Además, no olvides el módulo collections.
¡Felicitaciones! Has completado el laboratorio de Comprensiones de Lista. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.