Questi sono alcuni esempi dell'utilizzo degli indici per accedere ai singoli elementi di una lista:
>>> list = ['zero','one','two','three','four','five'] >>> list[0] 'zero' >>> list[4] 'four' >>> list[5] 'five'Questi esempi dovrebbero esservi familiari. Se volete estrarre il primo elemento di una lista dovrete richiamare l'elemento con indice 0, il secondo elemento avrà indice 1 e così via attraverso la lista. Come fare se volete l'ultimo elemento della lista ? Una via potrebbe essere quella di utilizzare la funzione
len
all'interno delle parentesi quadre:
list[len(list)-1]
. len
ritorna sempre l'ultimo indice
più uno. Allo stesso modo l'istruzione per avere il penultimo elemento
della lista sarà list[len(list)-2]
. Esiste una via più
semplice: in Python l'ultimo elemento è sempre indicizzato come -1, il
penultimo come -2 e così via. Ecco un'altro esempio:
>>> list[len(list)-1] 'five' >>> list[len(list)-2] 'four' >>> list[-1] 'five' >>> list[-2] 'four' >>> list[-6] 'zero'Così ogni elemento in una lista può essere indicizzato in due modi differenti: dall'inizio della lista e dalla fine della lista.
Un'altro metodo molto funzionale per estrarre elementi da una lista sono le sezioni. Ecco un'altro esempio per avere un'idea di come usarle:
>>> list = [0,'Fred',2,'S.P.A.M.','Stocking',42,"Jack","Jill"] >>> list[0] 0 >>> list[7] 'Jill' >>> list[0:8] [0, 'Fred', 2, 'S.P.A.M.', 'Stocking', 42, 'Jack', 'Jill'] >>> list[2:4] [2, 'S.P.A.M.'] >>> list[4:7] ['Stocking', 42, 'Jack'] >>> list[1:5] ['Fred', 2, 'S.P.A.M.', 'Stocking']Le sezioni sono utilizzate per estrarre parti di liste. La sintassi per estrarre sezioni è
list[primo_indice:ultimo_indice]
.
La sezione selezionata va da primo_indice
all'indice prima di
ultimo_indice
. È possibile utilizzare entrambi i metodi di
indicizzazione:
>>> list[-4:-2] ['Stocking', 42] >>> list[-4] 'Stocking' >>> list[-4:6] ['Stocking', 42]Un'altro trucco con le sezioni è non specificare l'indice. Se il primo indice non viene specificato, Python assumerà il primo indice della lista come indice da cui partire. Se il successivo indice non è specificato, si intenderà tutto il resto della lista. Ecco altri esempi:
>>> list[:2] [0, 'Fred'] >>> list[-2:] ['Jack', 'Jill'] >>> list[:3] [0, 'Fred', 2] >>> list[:-5] [0, 'Fred', 2]Ancora un'altro programma d'esempio (copiate ed incollate, se volete, la definizione di poem):
poem = ["<B>","Jack","and","Jill","</B>","went","up","the","hill","to","<B>",\ "fetch","a","pail","of","</B>","water.","Jack","fell","<B>","down","and",\ "broke","</B>","his","crown","and","<B>","Jill","came","</B>","tumbling",\ "after"] def get_bolds(list): true = 1 false = 0 ## Dichiara is_bold come falso, quindi stiamo guardando una ## porzione di testo non in grassetto. is_bold = false ## start_block rappresenta l'indice delle porzioni di testo in ## grassetto. start_block = 0 for index in range(len(list)): ## TAG che rappresenta l'inizio del grassetto. if list[index] == "<B>": if is_bold: print "Error: Extra Bold" ##print "Not Bold:",list[start_block:index] is_bold = true start_block = index+1 ## TAG che rappresenta la fine del grassetto. ## Ricordate che l'ultimo numero in una sezione ## rappresenta l'indice e dopo l'ultimo indice usato. if list[index] == "</B>": if not is_bold: print "Error: Extra Close Bold" print "Bold [",start_block,":",index,"] ",\ list[start_block:index] is_bold = false start_block = index+1 get_bolds(poem)E questo è l'output:
Bold [ 1 : 4 ] ['Jack', 'and', 'Jill'] Bold [ 11 : 15 ] ['fetch', 'a', 'pail', 'of'] Bold [ 20 : 23 ] ['down', 'and', 'broke'] Bold [ 28 : 30 ] ['Jill', 'came']
La funzione get_bold
scorre una lista dividendola in parole
e chiamate. Le chiamate che cerca sono <B>
che inizia il testo
in grassetto e <\B>
che lo termina. La funzione get_bold
ricerca l'inizio e la fine delle chiamate.
La prossima funzione delle liste è la copia. Se volete, potete provare questo semplice esempio:
>>> a = [1,2,3] >>> b = a >>> print b [1, 2, 3] >>> b[1] = 10 >>> print b [1, 10, 3] >>> print a [1, 10, 3]Probabilmente vi sorprenderà in quanto una modifica a b modifica anche a. Questo grazie all'istruzione
b = a
che
restituisce b come riferimento ad a. Significa che
b non è altro che un'altro nome per riferirsi ad a, il
risultato è che una modifica a b è una modifica ad a. Ciò
nonostante alcune tipologie di assegnamento non significano la
creazione di un doppio nome per una lista:
>>> a = [1,2,3] >>> b = a*2 >>> print a [1, 2, 3] >>> print b [1, 2, 3, 1, 2, 3] >>> a[1] = 10 >>> print a [1, 10, 3] >>> print b [1, 2, 3, 1, 2, 3]
In questo caso b non è un riferimento ad a in quanto
l'istruzione a*2
crea una nuova lista. b quindi si
riferisce ad a*2
e non ad a. Tutti gli assegnamenti
creano un riferimento. Quando passate una lista come argomento ad una
funzione create un riferimento. La maggior parte delle volte non
dovrete preoccuparvi di creare un riferimento anziché una
copia. Tuttavia, quando dovete modificare una lista senza cambiarne
un'altra, assegnata ad un nome differente, dovete assicurarvi di aver
creato una copia e non un riferimento.
Esistono diversi modi per copiare una lista. Il modo più semplice è usare le sezioni poiché creano sempre una nuova lista perfino se la sezione comprende tutta la lista:
>>> a = [1,2,3] >>> b = a[:] >>> b[1] = 10 >>> print a [1, 2, 3] >>> print b [1, 10, 3]
La sezione [:] crea una nuova copia della lista. In questo modo si può copiare una lista, ma qualsiasi sottolista creata in seguito si riferirà alla rispettiva sottolista della lista originale. Potete ovviare al problema copiando anche le sottoliste usando la funzione deepcopy del modulo copy:
>>> import copy >>> a = [[1,2,3],[4,5,6]] >>> b = a[:] >>> c = copy.deepcopy(a) >>> b[0][1] = 10 >>> c[1][1] = 12 >>> print a [[1, 10, 3], [4, 5, 6]] >>> print b [[1, 10, 3], [4, 5, 6]] >>> print c [[1, 2, 3], [4, 12, 6]]Innanzitutto notate che a è una lista di liste. L'istruzione
b[0][1] = 10
cambia sia la lista b che la lista a,
mentre c rimane inalterata. Questo accade perché b
continua ad essere un riferimento ad a se vengono utilizzate le
sezioni; c invece è una copia completa, ottenuta grazie alla
funzione deepcopy.
Perciò dovrete preoccuparvi dei riferimenti ogni volta che userete la funzione ``=''? La buona notizia è che dovrete occuparvi dei riferimenti solamente quando utilizzate dizionari e liste. Numeri e stringhe creano dei riferimenti, ma quando vengono modificati creano una copia, quindi non potrete mai modificarli inaspettatamente.
Adesso vi starete probabilmente chiedendo perché vengono usati i riferimenti. La motivazione, sostanzialmente, è la loro velocità. È molto più veloce fare un riferimento ad una lista di migliaia di riferimenti che copiarli tutti. Un'altra ragione è che permettono di avere una funzione che modifichi una lista o un dizionario. Tenete in considerazione tutto questo se vi troverete ad avere strani errori in relazione a dati modificati quando quest'ultimi non avrebbero dovuto subire alcun cambiamento.