16.4. Revisión de la relación de listas

Ya está familiarizado con el uso de listas por comprensión para hacer corresponder una a otra. Hay otra manera de conseguir lo mismo usando la función incorporada map. Funciona muy parecido a filter.

Ejemplo 16.10. Presentación de map

>>> def double(n):
...     return n*2
...     
>>> li = [1, 2, 3, 5, 9, 10, 256, -3]
>>> map(double, li)                       1
[2, 4, 6, 10, 18, 20, 512, -6]
>>> [double(n) for n in li]               2
[2, 4, 6, 10, 18, 20, 512, -6]
>>> newlist = []
>>> for n in li:                          3
...     newlist.append(double(n))
...     
>>> newlist
[2, 4, 6, 10, 18, 20, 512, -6]
1 map toma una función y una lista[19] y devuelve una lista nueva invocando la función sobre cada elemento de la lista, por orden. En este caso la función simplemente multiplica cada elemento por 2.
2 Podría conseguir lo mismo con una lista por comprensión. Las listas por comprensión se introdujeron por primera vez en Python 2.0; map lleva ahí desde el principio.
3 Podría usar un bucle for para conseguir lo mismo, si insistiera en pensar como un programador de Visual Basic.

Ejemplo 16.11. map con listas de tipos de datos distintos

>>> li = [5, 'a', (2, 'b')]
>>> map(double, li)                       1
[10, 'aa', (2, 'b', 2, 'b')]
1 Como nota de interés, quisiera señalar que map funciona también con listas de tipos datos distintos, siempre que la función los trate correctamente. En este caso la función double se limita a multiplicar un argumento dado por 2, y Python hace Lo Correcto dependiendo del tipo de dato del argumento. Para los enteros significa multiplicarlos por 2; para las cadenas significa concadenar la cadena consigo misma; para las tiplas significa crear una nueva tupla que tenga todos los elementos de la original, y luego de nuevo esos elementos.

Bien, basta de jugar. Veamos algo de código real.

Ejemplo 16.12. map en regression.py

    filenameToModuleName = lambda f: os.path.splitext(f)[0] 1
    moduleNames = map(filenameToModuleName, files)          2
1 Como vio en Sección 4.7, “Utilización de las funciones lambda”, lambda define una función en línea (inline). Y también vio en Ejemplo 6.17, “Dividir nombres de rutas” que os.path.splitext toma el nombre de un fichero y devuelve una tupla (nombre, extensión). Así que filenameToModuleName es una función que tomará un nombre de fichero y eliminará la extensión para devolver sólo el nombre.
2 La invocación a map toma cada nombre de fichero listado en files, lo pasa a la función filenameToModuleName, y devuelve una lista de los valores de retorno de cada una de estas invocaciones. En otras palabras, elimina la extensión de fichero de cada nombre y almacena la lista de estos nombres sin extensión en moduleNames.

Como verá en el resto del capítulo, podemos extender este tipo de forma de pensar centrada en los datos hasta el objetivo final, que es definir y ejecutar una única batería de pruebas que contenga las pruebas de todas esas otras baterías a menor escala.

Footnotes

[19] De nuevo, debería señalar que map puede tomar una lista, una tupla o cualquier objeto que actúe como una secuencia. Vea la nota anterior sobre filter.