2.13. Mappare le liste

Una delle più potenti caratteristiche di Python sono le list comprehension (descrizioni di lista), che utilizzano una tecnica compatta per mappare una lista in un'altra, applicando una funzione ad ognuno degli elementi della lista.

Esempio 2.31. Introduzione alle list comprehension

>>> 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 Per fare luce su questo costrutto guardatelo da destra verso sinistra. li è la lista che state mappando. Python esegue un ciclo su li un'elemento alla volta, assegnando temporaneamente il valore di ogni elemento alla variabile elem. Dopodiché Python applica la funzione elem*2 ed aggiunge il risultato alla lista di ritorno (usando il metodo “append()” n.d.T.).
2 Osservate che la list comprehension non modifica la lista originale.
3 È perfettamente sicuro assegnare il risultato di una list comprehension alla variabile che state mappando. Non ci sono particolari condizioni od altre stranezze di cui tener conto; Python crea la nuova lista in memoria e quando la descrizione di lista è completa, assegna il risultato alla nuova variabile.

Esempio 2.32. List comprehension in buildConnectionString

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

Notate che state chiamando la funzione items del dizionario params. Questa funzione ritorna una lista di tuple di tutti i dati del dizionario.

Esempio 2.33. chiavi, valori ed elementi

>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> params.keys()   1
['server', 'uid', 'database', 'pwd']
>>> params.values() 2
['mpilgrim', 'sa', 'master', 'secret']
>>> params.items()  3
[('server', 'mpilgrim'), ('uid', 'sa'), ('database', 'master'), ('pwd', 'secret')]
1 Il metodo keys di un dizionario ritorna una lista di tutte le sue chiavi. La lista non è nell'ordine di come il dizionario è stato definito (ricordate, gli elementi di un dizionario non hanno un ordine), ma è una lista.
2 Il metodo values ritorna una lista di tutti i valori. La lista è nello stesso ordine della lista ritornata da keys, così che params.values()[n] == params[params.keys()[n]] per tutti i valori di n.
3 Il metodo items ritorna una lista di tuple nella forma (key, value). La lista contiene tutti i dati del dizionario.

Adesso guardiamo cosa fa la funzione buildConnectionString. Prende una lista, params.items() e la mappa in una nuova lista applicando la formattazione delle stringhe ad ogni elemento. La nuova lista avrà lo stesso numero di elementi di params.items(), ma ogni elemento della nuova lista sarà una stringa che contiene una chiave ed il relativo valore associato, proveniente dal dizionario params.

Esempio 2.34. List comprehension in buildConnectionString, passo per passo

>>> 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 Notate che stiamo usando due variabili per iterare attraverso la lista params.items(). Questo è un altro uso dell'assegnamento multi-variabile. Il primo elemento di params.items() è ('server', 'mpilgrim'), perciò nella prima iterazione della list comprehension, k otterrà il valore 'server' e v otterrà 'mpilgrim'. In questo caso, ignorando il valore di v ed includendo solo il valore di k nella lista di ritorno, questa descrizione di lista finirà per essere equivalente a params.keys(). (Voi non usereste mai una descrizione di lista come questa in codice reale; è solo un semplice esempio per farvi capire ciò che avviene.)
2 Qui stiamo facendo la stessa cosa, ma ignorando il valore di k, così che questa list comprehension diventi equivalente a params.values().
3 Combinando i due esempi precedenti con qualche semplice formattazione di stringa, otteniamo una lista di stringhe che includono sia la chiave che il valore di ogni elemento del dizionario. Questo pare sospetto, come l'output del programma; tutto quello che rimane è unire gli elementi di questa lista in una singola stringa.

Ulteriori letture