Abbiamo già esaminato le liste e come vengono utilizzate. Ora che avete un background più corposo entrerò più in dettaglio. Innanzitutto scopriremo altri modi per estrarre gli elementi dalle liste, quindi analizzeremo un metodo per copiarle.
Questi sono alcuni esempi dell'utilizzo degli
indici per accedere ai singoli elementi di una
lista:
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 + 1. Nello
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'esempio:
>>> list = ['zero','one','two','three','four','five']
>>> list[0]
'zero'
>>> list[4]
'four'
>>> list[5]
'five'
Così ogni elemento in una lista può essere
indicizzato in due modi differenti, dall'inizio
della lista e dalla fine della lista.>>> list[len(list)-1]
'five'
>>> list[len(list)-2]
'four'
>>> list[-1]
'five'
>>> list[-2]
'four'
>>> list[-6]
'zero'
Un'altra via molto utile per estrarre elementi
da una lista sono le sezioni. Ecco un'altro
esempio:
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.
E' possibile utilizzare entrambi i
metodi di indicizzazione:
>>> 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']
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:
Ecco un'altro esempio:
>>> list[-4:-2]
['Stocking', 42]
>>> list[-4]
'Stocking'
>>> list[-4:6]
['Stocking', 42]
Ancora un'altro programma d'esempio:
>>> list[:2]
[0, 'Fred']
>>> list[-2:]
['Jack', 'Jill']
>>> list[:3]
[0, 'Fred', 2]
>>> list[:-5]
[0, 'Fred', 2]
E questo è l'output:
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
## is_bold tells whether or not the we are currently looking at
## a bold section of text.
is_bold = false
## start_block is the index of the start of either an unbolded
## segment of text or a bolded segment.
start_block = 0
for index in range(len(list)):
##Handle a starting of bold text
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
##Handle end of bold text
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)
La funzione get_bold
scorre per una lista dividendola
in parole e chiamate. Le chiamate che
cerca sono <B>
che inizia il testo in
grassetto e <\B>
che lo termina.
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 prossima funzione delle liste è copiarle:
Questo è probabilmente sorprendente 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 riferimento:
>>> a = [1,2,3]
>>> b = a
>>> print b
[1, 2, 3]
>>> b[1] = 10
>>> print b
[1, 10, 3]
>>> print a
[1, 10, 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.
Ciò nonostante, 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:
>>> 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 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 :
>>> a = [1,2,3]
>>> b = a[:]
>>> b[1] = 10
>>> print a
[1, 2, 3]
>>> print b
[1, 10, 3]
Innanzitutto notate che a
è una lista di liste.
L'istruzione b[0][1] = 10
cambia sia la lista
b che la lista
a, c
invece resta uguale. Questo accade perché
b continua ad essere un
riferimento ad a
se vengono utilizzate le sezioni;
c invece è una copia
ottenuta grazie alla funzione
deepcopy.
>>> 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]]
Dovrete preoccuparvi 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 ragione basilare è per la loro velocità. E' molto più veloce fare un riferimento a 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. Tenetene quindi conto se vi troverete ad avere strani errori in relazione a dati modificati quando quest'ultimi non avrebbero dovuto subire alcun cambiamento.