1.13. Correspondencia de listas

Una de las más potentes características de Python es la creación de listas por comprensión, que proporciona una forma compacta de relacionar una lista con otra aplicando una función a los elementos de la primera.

Ejemplo 1.30. Introducción a las listas por comprensión

>>> li = [1, 9, 8, 4]
>>> [elem*2 for elem in li]      1
[2, 18, 16, 8]
>>> li                           2
[1, 9, 8, 4]
>>> li = [elem*2 for elem in li] 3
>>> li
[2, 18, 16, 8]
1 Para hacerse una idea de esto, mírelo de derecha a izquierda. li es la lista a la que se aplica la relación. Python recorre esta lista elemento por elemento, asignando temporalmente el valor de cada uno de ellos a la variable elem. A continuación, Python aplica la función elem*2 y añade el resultado a la lista que se devuelve.
2 Advierta que al crear una lista por comprensión no se modifica la lista original.
3 No hay riesgo en asignar el resultado de una lista creada por comprensión a la variable a que se aplica la relación. No hay nada de qué preocuparse: Python construye la nueva lista en memoria, y cuando la operación ha terminado, se asigna el resultado a la variable.

Ejemplo 1.31. Listas por comprensión en buildConnectionString

["%s=%s" % (k, v) for k, v in params.items()]

En primer lugar, advierta que se está llamando a la función items del diccionario params. Esta función devuelve una lista de tuplas con todos los datos del diccionario.

Ejemplo 1.32. keys, values, e items

>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> params.keys()   1
['server', 'uid', 'database', 'pwd']
>>> params.values() 2
['mpilgrim', 'master', 'sa', 'secret']
>>> params.items()  3
[('server', 'mpilgrim'), ('uid', 'sa'), ('database', 'master'), ('pwd', 'secret')]
1 El método keys de un diccionario devuelve una lista de todas las claves. La lista no está en el orden en que se definió el diccionario (recuerde, los elementos de un diccionario no guardan orden), pero es una lista.
2 El método values devuelve una lista con todos los valores. La lista está en el mismo orden que la devuelta por keys, de modo que params.values()[n] == params[params.keys()[n]] para todos los valores de n.
3 El método items devuelve una lista de tuplas de la forma (key, valor). La lista contiene todos los datos del diccionario.

Veamos ahora qué hace buildConnectionString. Toma una lista, params.items(), y la transforma en una nueva lista aplicando el formato de cadenas a cada elemento. La nueva lista tendrá el mismo número de elementos que params.items(), pero cada elemento de la nueva lista será una cadena que contiene tanto la clave como su valor asociado en el diccionario params.

Ejemplo 1.33. Listas por comprensión en buildConnectionString, paso a paso

>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> params.items()
[('server', 'mpilgrim'), ('uid', 'sa'), ('database', 'master'), ('pwd', 'secret')]
>>> [k for k, v in params.items()]                1
['server', 'uid', 'database', 'pwd']
>>> [v for k, v in params.items()]                2
['mpilgrim', 'sa', 'master', 'secret']
>>> ["%s=%s" % (k, v) for k, v in params.items()] 3
['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']
1 Advierta que estamos usando dos variables para recorrer la lista params.items(). Este es otro uso de la asignación múltiple. El primer elemento de params.items() es ('server', 'mpilgrim'), de modo que en el primer ciclo de la relación, k tomará el valor 'server' y v el valor 'mpilgrim'. En este caso ignoramos el valor de v y sólo incluimos el de k en la lista devuelta, por lo que esta relación equivale finalmente a params.keys(). (No se utilizaría realmente una relación de listas como esta en el código real; es sólo un ejemplo demasiado simple para entender qué pasa aquí).
2 Aquí hacemos lo mismo, pero ignoramos el valor de k, de manera que esta relación equivale finalmente a params.values().
3 Combinando los dos ejemplos anteriores con un simple formato de cadenas, obtenemos una lista de cadenas que incluyen tanto la clave como el valor de cada elemento del diccionario. Esto se parece sospechosamente a la salida del programa; todo lo que queda por hacer es unir los elementos de esta lista en una única cadena.

Lecturas complementarias