Listas por comprensión en Python

Las listas por comprensión o list comprehension es una característica muy práctica de Python (también incluida en otros lenguajes de programación). Es una herramiente de mucha utilidad y fácil de usar, muchas veces desconocida por quienes vienen de lenguajes como PHP o Java.
Este artículo tiene como objetivo explorar su uso y plantear ejemplos para que los nuevos usuarios puedan incorporarlas rápidamente a su cajita de herramientas.

Cómo lo indica el PEP 202, es una construcción sintáctica que permite crear listas en situaciones en las que se usaría map, filter o for anidados; pero de forma mas concisa.

map

Al llamar a la función map con argumentos f y l ,dónde f es una función y l una lista, retorna una lista con los resultados de aplicar f a cada elemento de l.
En el primer ejemplo usamos la función len, que dado un string retorna su longitud:

>>> len('hola')
4

Esto es lo que sucede al aplicar map a todos los elementos de una lista de palabras:

>>> palabras = ['uno', 'dos', 'Santa Fe', 'Python', '...', 'Soleado']
>>> map(len, palabras)
[3, 3, 8, 6, 3, 7]

La versión equivalente es:

>>> [len(p) for p in palabras]
[3, 3, 8, 6, 3, 7]

La sintaxis de la listas por comprensión es más flexible. Si queremos la lista de palabras, pero en mayúsculas hacemos:

>>> [p.upper() for p in palabras]
['UNO', 'DOS', 'SANTA FE', 'PYTHON', '...', 'SOLEADO']

Para hacer lo anterior utilizando la función map, antes tendríamos que definir una función que llame al método upper de la clase string:

>>> def upper(s):
    return s.upper()
>>> map(upper, palabras)
['UNO', 'DOS', 'SANTA FE', 'PYTHON', '...', 'SOLEADO']

filter

La función filter recibe como argumento una función f y una lista l. Al igual que map, aplica f a todos los elementos de l pero retorna una lista con los elementos de l para los cuales la función f retornó True o un objeto con valor de verdad True.

>>> def incluye_n(s):
    return 'N' in s.upper()
>>> incluye_n('Python')
True
>>> incluye_n('Soleado')
False
>>> filter(incluye_n, palabras)
['uno', 'Santa Fe', 'Python']

La forma de hacer lo anterior con listas por comprensión es:

>>> [p for p in palabras if incluye_n(p)]
['uno', 'Santa Fe', 'Python']

Incluso muchas veces podemos hacerlo sin necesitar de definir una función auxiliar:

>>> [p for p in palabras if 'N' in p.upper()]
['uno', 'Santa Fe', 'Python']

for

También podemos anidar fors de forma similar a cómo lo haríamos en:

>>> range(6)
[0, 1, 2, 3, 4, 5]
>>> for n in range(6):
for p in palabras:
    if len(p) == n:
        print p,n
uno 3
dos 3
... 3

Pero con una sintaxis más cómoda:

>>> [(p,n) for n in range(6) for p in palabras]
[('uno', 0), ('dos', 0), ('Santa Fe', 0), ('Python', 0), ('...', 0), ('Soleado', 0), ('uno', 1), ('dos', 1), ('Santa Fe', 1), ('Python', 1), ('...', 1), ('Soleado', 1), ('uno', 2), ('dos', 2), ('Santa Fe', 2), ('Python', 2), ('...', 2), ('Soleado', 2), ('uno', 3), ('dos', 3), ('Santa Fe', 3), ('Python', 3), ('...', 3), ('Soleado', 3), ('uno', 4), ('dos', 4), ('Santa Fe', 4), ('Python', 4), ('...', 4), ('Soleado', 4), ('uno', 5), ('dos', 5), ('Santa Fe', 5), ('Python', 5), ('...', 5), ('Soleado', 5)]
>>> [(p,n) for n in range(6) for p in palabras if len(p) == n]
[('uno', 3), ('dos', 3), ('...', 3)]

About Juanjo

Mi nombre es Juanjo Conti, vivo en Santa Fe y soy Ingeniero en Sistemas de Información. Mi lenguaje de programación de cabecera es Python; lo uso para trabajar, estudiar y jugar. Como hobby escribí un libro de cuentos que se puede descargar gratuitamente.
This entry was posted in General and tagged . Bookmark the permalink.
  • http://willy-n-billy.blogspot.com hugo_dc

    Muy interesante este pequeño artículo.

    Salu2, Ojalá y sigas publicando más cosas interesantes sobre Python.

  • http://www.miltonpividori.com.ar Milton Pividori

    Muy útil y práctico. En Boo también están, no sabía:


    >>>palabras = ['uno', 'dos', 'Santa Fe', 'Python', '...', 'Soleado']
    ['uno', 'dos', 'Santa Fe', 'Python', '...', 'Soleado']
    >>>resultado = [len(p) for p in palabras]
    [3, 3, 8, 6, 3, 7]
    >>>resultado = [p.ToUpper() for p in palabras]
    ['UNO', 'DOS', 'SANTA FE', 'PYTHON', '...', 'SOLEADO']
    >>>resultado = [(p,n) for n in range(6) for p in palabras]
    [('uno', 0), ('dos', 0), ('Santa Fe', 0), ('Python', 0), ('...', 0),...]

    En C# con LINQ se pueden hacer cosas parecidas. Este es un ejemplo de LINQ to Objects:


    List palabras = new List {"uno", "dos", "tres", "Python", "Sol"};

    var largas = from p in palabras
    where p.Contains("n")
    select p + "(" + p.Length + ")";

    foreach(var m in largas)
    Console.WriteLine(m);

    Lo interesante de LINQ es que se puede utilizar también para realizar consultas a una base de datos relacional (LINQ to SQL), a un archivo XML (LINQ to XML), etc.