2.5. Filtrado de listas

Como ya sabe, Python tiene una potente capacidad para convertir una lista en otra por medio de las relaciones de listas. Esto puede combinarse con un mecanismo de filtrado en el que algunos elementos de la lista se utilicen mientras otros se pasen por alto.

Ejemplo 2.13. Sintaxis del filtrado de listas

[expresión de relación for elemento in lista origen if expresión de filtrado]

Esto es una extensión de la relación de listas que usted conoce y tanto le gusta. Las dos primeras partes son como antes; la última parte, la que comienza con if, es la expresión de filtrado. Una expresión de filtrado puede ser cualquier expresión que se evalúe como verdadera o falsa (lo cual, en Python, puede ser casi cualquier resultado). Cualquier elemento para el cual la expresión resulte verdadera, será incluido en el proceso de relación. Todos los demás elementos se pasan por alto, de modo que no pasan por el proceso de relación y no se incluyen en la lista final.

Ejemplo 2.14. Presentación del filtrado de listas

>>> li = ["a", "mpilgrim", "foo", "b", "c", "b", "d", "d"]
>>> [elem for elem in li if len(elem) > 1]       1
['mpilgrim', 'foo']
>>> [elem for elem in li if elem != "b"]         2
['a', 'mpilgrim', 'foo', 'c', 'd', 'd']
>>> [elem for elem in li if li.count(elem) == 1] 3
['a', 'mpilgrim', 'foo', 'c']
1 Esta expresión de relación es sencilla (simplemente devuelve el valor de cada elemento), así que concentrémonos en la expresión de filtrado. Mientras Python recorre la lista, aplica la expresión de filtrado a cada elemento; si la expresión es verdadera, se aplica la relación al elemento y el resultado se incluye en la lista final. Aquí estamos filtrando todas las cadenas de un solo carácter, por lo que se obtendrá una lista con todas las cadenas más largas.
2 Aquí filtramos un valor concreto, b. Observe que esto filtra todas las apariciones de b, ya que cada vez que este valor aparezca, la expresión de filtrado será falsa.
3 count es un método de lista que devuelve el número de veces que aparece un valor en una lista. Se podría pensar que este filtro elimina los valores duplicados en una lista, devolviendo otra que contiene una única copia de cada valor de la lista original. Pero no es así, porque los valores que aparecen dos veces en la lista original (en este caso, b y d) son completamente excluidos. Hay modos de eliminar valores duplicados en una lista, pero el filtrado no es la solución.

Ejemplo 2.15. Filtrado de una lista en apihelper.py

    methodList = [method for method in dir(object) if callable(getattr(object, method))]

Esto parece complicado, y lo es, pero la estructura básica es la misma. La expresión de filtrado devuelve una lista, que se asigna a la variable methodList. La primera mitad de la expresión es la parte de relación. Es una relación de identidad; devuelve el valor de cada elemento. dir(object) devuelve la lista de los atributos y métodos de object; esa es la lista a que se aplica la relación. Luego la única parte nueva es la expresión de filtrado que sigue a if.

La expresión de filtrado parece que asusta, pero no. Usted ya conoce callable, getattr, e in. Como se vio en la sección anterior, la expresión getattr(object, method) devuelve un objeto función si object es un módulo y method el nombre de una función de ese módulo.

Por tanto esta expresión toma un objeto, llamado object, obtiene la lista de sus atributos, métodos, funciones y algunas cosas más, y a continuación filtra esta lista para eliminar todo lo que no nos interesa. Esto lo hacemos tomando el nombre de cada atributo/método/función y obteniendo una referencia al objeto real por medio de la función getattr. Después comprobamos si ese objeto puede ser llamado, como lo serán los métodos y funciones, tanto incorporados (como el método pop de una lista) como definidos por el usuario (como la función buildConnectionString del módulo odbchelper). No nos interesan otros atributos, como el atributo __name__ que está incorporado en todos los módulos.

Lecturas complementarias