Nella programmazione Python, la comprensione e l’utilizzo efficace degli iterabili è fondamentale per creare codice efficace. Gli iterabili sono oggetti attraverso i quali è possibile iterare o creare un loop. Supportano lo scorrimento sequenziale degli elementi al loro interno, il che li rende uno strumento fondamentale per accedere e manipolare elementi in oggetti o strutture di dati.
Questo articolo spiega come utilizzare correttamente gli iterabili in Python, concentrandosi sui tipi di dati iterabili integrati nel linguaggio: liste, tuple, dizionari, stringhe e set. Inoltre, spiega come implementare tipi di iterabili personalizzati ed eseguire operazioni avanzate.
Come eseguire il loop degli iterabili in Python
In Python, è possibile iterare attraverso diversi tipi di iterabili utilizzando un ciclo for
. Ciò permette di navigare in sequenze e di eseguire operazioni su singoli elementi all’interno di liste, set e dizionari.
La parola chiave for
in Python si discosta dalla sua utilità in altri linguaggi orientati agli oggetti come Java. I loop di Python for
funzionano più come i metodi degli iteratori. Ecco alcuni esempi che dimostrano i loop negli iteratori:
1. Loop in una lista
Gli elenchi sono raccolte ordinate di elementi che consentono una facile iterazione con un ciclo for
.
fruits_list = ["Apple", "Mango", "Peach", "Orange", "Banana"]
for fruit in fruits_list:
print(fruit)
Nel codice qui sopra, fruit
agisce come un iteratore che il ciclo utilizza per scorrere ogni elemento dell’elenco e contemporaneamente stamparlo. Il ciclo termina dopo aver valutato l’ultimo elemento dell’elenco. Il codice precedente dovrebbe dare il seguente risultato:
Apple
Mango
Peach
Orange
Banana
2. Iterare una tupla
Le tuple sono simili alle liste ma sono immutabili. Si possono iterare proprio come le liste.
fruits_tuple = ("Apple", "Mango", "Peach", "Orange", "Banana")
for fruit in fruits_tuple:
print(fruit)
In questo esempio, il ciclo for
itera attraverso la tupla e ad ogni iterazione la variabile fruit
assume il valore dell’elemento corrente della tupla. Il codice dovrebbe dare il seguente risultato:
Apple
Mango
Peach
Orange
Banana
3. Looping attraverso i set
I set sono raccolte non ordinate di elementi unici. Si possono scorrere utilizzando un ciclo for
.
fruits_set = {"Apple", "Mango", "Peach", "Orange", "Banana"}
for fruit in fruits_set:
print(fruit)
In questo esempio, il ciclo for
itera attraverso il set. Tuttavia, poiché gli insiemi non sono ordinati, l’ordine di iterazione potrebbe non corrispondere all’ordine in cui gli elementi sono stati definiti nel set. In ogni iterazione, la variabile fruit
assume il valore dell’elemento corrente dell’insieme. Il codice dovrebbe dare un risultato simile al seguente (l’ordine può variare):
Mango
Banana
Peach
Apple
Orange
4. Iterazione di stringhe
Le stringhe sono sequenze di caratteri che si possono scorrere carattere per carattere.
string = "Kinsta"
for char in string:
print(char)
Il codice qui sopra itera la stringa “Kinsta” e stampa ogni carattere su una nuova riga. In ogni iterazione, la variabile char
assume il valore del carattere corrente della stringa. Il codice dovrebbe dare il seguente risultato:
K
i
n
s
t
a
5. Scorrimento di un dizionario
L’utilizzo del ciclo for
è simile per liste, set, tuple e stringhe, ma è diverso per i dizionari, che utilizzano coppie chiave-valore per memorizzare gli elementi. I dizionari rappresentano un caso unico per l’esecuzione del ciclo, in quanto è possibile iterarli utilizzando approcci diversi. Ecco i diversi approcci che si possono utilizzare per scorrere un dizionario in Python:
- Iterazione attraverso le chiavi:
countries_capital = { "USA": "Washington D.C.", "Australia": "Canberra", "France": "Paris", "Egypt": "Cairo", "Japan": "Tokyo" } for country in countries_capital.keys(): print(country)
Il codice precedente definisce un dizionario chiamato
countries_capital
, dove i nomi dei paesi sono le chiavi e le rispettive capitali sono i valori. Il ciclofor
esegue l’iterazione delle chiavi del dizionariocountries_capital
utilizzando il metodokeys()
. Questo metodo restituisce un oggetto vista che visualizza un elenco delle chiavi del dizionario, il che facilita l’esecuzione del ciclo su tutte le chiavi. Ad ogni iterazione, la variabilecountry
assume il valore della chiave corrente. Questo codice dovrebbe dare il seguente risultato:USA Australia France Egypt Japan
- Iterazione dei valori:
countries_capital = { "USA": "Washington D.C.", "Australia": "Canberra", "France": "Paris", "Egypt": "Cairo", "Japan": "Tokyo" } for capital in countries_capital.values(): print(capital)
Nel codice qui sopra,
for
itera i valori del dizionariocountries_capital
utilizzando il metodovalues()
. Questo metodo restituisce un oggetto vista che visualizza un elenco dei valori del dizionario, rendendo più semplice l’iterazione di tutti i valori. Ad ogni iterazione, la variabilecapital
assume il valore del valore corrente nell’elenco. Questo codice dovrebbe dare il seguente risultato:Washington D.C. Canberra Paris Cairo Tokyo
- Iterazione di coppie chiave-valore:
countries_capital = { "USA": "Washington D.C.", "Australia": "Canberra", "France": "Paris", "Egypt": "Cairo", "Japan": "Tokyo" } for country, capital in countries_capital.items(): print(country, ":", capital)
Il codice qui sopra mostra come iterare sia le chiavi che i valori del dizionario
countries_capital
utilizzando il metodoitems()
. Il metodoitems()
restituisce un oggetto vista che visualizza un elenco di tuple chiave-valore del dizionario. Nel ciclofor
, ogni iterazione scompone una coppia chiave-valore dall’elemento corrente dell’elenco. Alle variabilicountry
ecapital
vengono assegnati rispettivamente la chiave e il valore corrispondenti. Questo codice dovrebbe dare il seguente risultato:USA : Washington D.C. Australia : Canberra France : Paris Egypt : Cairo Japan : Tokyo
Iterazione avanzata con enumerate() in Python
Un altro modo per iterare su iterabili in Python restituendo sia l’indice che il valore corrispondente degli elementi è la funzione enumerate()
. Diamo uno sguardo a questo esempio:
fruits_list = ["Apple", "Mango", "Peach", "Orange", "Banana"]
for index, fruit in enumerate(fruits_list):
print(fruit, index)
Ecco l’output:
Apple 0
Mango 1
Peach 2
Orange 3
Banana 4
La funzione enumerate
permette anche di specificare l’indice iniziale, oltre a 0
, per l’operazione di iterazione. Possiamo modificare l’esempio precedente come segue:
fruits_list = ["Apple", "Mango", "Peach", "Orange", "Banana"]
for index, fruit in enumerate(fruits_list, start = 2):
print(fruit, index)
Ecco l’output:
Apple 2
Mango 3
Peach 4
Orange 5
Banana 6
Notiamo che, sebbene questo esempio specifichi l’indice iniziale dell’enumerazione, enumerate
non applica un’indicizzazione a base zero all’iterabile, come avviene con le liste native. Applica semplicemente il valore iniziale al primo elemento dell’elenco fino all’ultimo.
Come implementare i generatori Python
I generatori sono speciali iterabili Python che permettono di costruire oggetti generatori senza creare esplicitamente tipi incorporati come liste, set o dizionari. Possiamo usare i generatori per produrre valori man mano in base alla logica di generazione.
I generatori utilizzano l’istruzione yield
per restituire i valori generati uno alla volta. Ecco un esempio di generatori iterabili:
def even_generator(n):
counter = 0
while counter <= n:
if counter % 2 == 0:
yield counter
counter += 1
for num in even_generator(20):
print(num)
Il codice fornito definisce una funzione even_generator
che produce una sequenza di numeri pari da 0
a un n
specificato utilizzando l’istruzione yield
. Utilizza un ciclo per generare questi valori e itera il risultato utilizzando l’iteratore num
, assicurando la valutazione di tutti i valori all’interno dell’intervallo indicato. Questo codice produce un elenco di numeri pari da 0
a 20
, come mostrato di seguito:
0
2
4
6
8
10
12
14
16
18
20
Possiamo ottenere una maggiore concisione quando lavoriamo con le espressioni del generatore. Ad esempio, possiamo progettare una funzione generatore che incorpori anche la logica del ciclo:
cube = (num ** 3 for num in range(1, 6))
for c in cube:
print(c)
In questo caso, assegniamo la variabile cube
al risultato di una funzione che calcola il cubo dei valori compresi nell’intervallo da 1 a 6. La funzione è in grado di generare un ciclo di valori all’interno dell’intervallo specificato. La funzione esegue poi un ciclo di valori all’interno dell’intervallo specificato, producendo i risultati del calcolo uno dopo l’altro. L’output è il seguente:
1
8
27
64
125
Come costruire iterabili personalizzati
Python permette di personalizzare ulteriormente le operazioni iterabili utilizzando gli iteratori. Gli oggetti iteratore implementano il protocollo iteratore e contengono due metodi: __iter__()
e __next__()
. Il metodo __iter__()
restituisce un oggetto iteratore, mentre __next__()
restituisce il valore successivo in un contenitore iterabile. Ecco un esempio di iteratori in Python:
even_list = [2, 4, 6, 8, 10]
my_iterator = iter(even_list)
print(next(my_iterator)) # Prints 2
print(next(my_iterator)) # Prints 4
print(next(my_iterator)) # Prints 6
In questo esempio, utilizziamo il metodo iter()
per creare un oggetto iteratore (my_iterator
) dall’elenco. Per accedere a ciascun elemento dell’elenco, avvolgiamo l’oggetto iteratore con il metodo next()
. Poiché gli elenchi sono collezioni ordinate, l’iteratore restituisce gli elementi in sequenza.
Gli iteratori personalizzati sono ideali per le operazioni che coinvolgono grandi insiemi di dati che non si possono caricare in memoria contemporaneamente. Poiché la memoria è costosa e soggetta a vincoli di spazio, possiamo usare un iteratore per elaborare gli elementi dei dati singolarmente senza caricare l’intero set di dati in memoria.
Funzioni iterabili
Python utilizza delle funzioni per spostarsi, manipolare e ispezionare gli elementi di una lista. Alcune funzioni comuni per gli elenchi sono:
sum
– restituisce la somma di un dato iterabile, a condizione che l’insieme sia di tipo numerico (numeri interi, valori in virgola mobile e numeri complessi)any
– restituiscetrue
se uno qualsiasi degli elementi dell’iterabile è vero. Altrimenti, restituiscefalse
.all
– restituiscetrue
se tutti gli elementi dell’iterabile sono veri. Altrimenti, restituiscefalse
.max
– restituisce il valore massimo di un dato insieme iterabilemin
– restituisce il valore minimo di un dato insieme iterabilelen
– restituisce la lunghezza di un dato iterabileappend
– aggiunge un valore alla fine di un elenco iterabile
L’esempio seguente mostra queste funzioni con un elenco:
even_list = [2, 4, 6, 8, 10]
print(sum(even_list))
print(any(even_list))
print(max(even_list))
print(min(even_list))
even_list.append(14) # Add 14 to the end of the list
print(even_list)
even_list.insert(0, 0) # Insert 0 and specified index [0]
print(even_list)
print(all(even_list)) # Return true only if ALL elements in the list are true
print(len(even_list)) # Print the size of the list
Ecco l’output:
30
True
10
2
[2, 4, 6, 8, 10, 14]
[0, 2, 4, 6, 8, 10, 14]
False
7
Nell’esempio precedente, la funzione append
aggiunge un singolo parametro (14
) alla fine dell’elenco. La funzione insert
permette di specificare l’indice di inserimento. Pertanto, even_list.insert(0, 0)
inserisce 0
all’indice [0]
.
L’istruzione print(all(even_list))
restituisce false
perché nell’elenco è presente un valore 0
, interpretato come false
. Infine, print(len(even_list))
restituisce la lunghezza dell’iterabile.
Operazioni iterabili avanzate
Python offre funzioni avanzate che favoriscono la concisione delle operazioni iterabili. Di seguito ne elenchiamo alcune.
1. Comprensioni di lista
Le comprensioni di lista permettono di creare nuovi elenchi applicando una funzione a ciascun elemento degli elenchi esistenti. Ecco un esempio:
my_numbers = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
even_number_list = [num for num in my_numbers if num%2 == 0]
print(even_number_list)
In questo frammento di codice, viene creata una lista chiamata my_numbers
con i numeri interi da 11
a 20
. L’obiettivo è quello di generare una nuova lista, even_number_list
, contenente solo numeri interi pari. Per raggiungere questo obiettivo, si applica una comprensione della lista che restituisce un intero da my_numbers
solo se quell’intero è pari. L’istruzione if
contiene la logica che restituisce i numeri pari.
Ecco l’output:
[12, 14, 16, 18, 20]
2. Zip
La funzione zip()
di Python combina più iterabili in tuple. Le tuple memorizzano più valori in un’unica variabile e sono immutabili. Ecco come combinare gli iterabili usando zip()
:
fruits = ["apple", "orange", "banana"]
rating = [1, 2, 3]
fruits_rating = zip(rating, fruits)
print(list(fruits_rating))
In questo esempio, fruits_rating
accoppia ogni valutazione con un frutto, creando un unico iterabile. L’output è:
[(1, 'apple'), (2, 'orange'), (3, 'banana')]
Questo codice agisce come un sistema di valutazione per diversi frutti, con il primo elenco (fruits
) che rappresenta i frutti e il secondo elenco che rappresenta le valutazioni su una scala da 1 a 3.
3. Filter
Un’altra funzione avanzata, filter, accetta due argomenti: una funzione e un iterabile. Applica la funzione a ogni elemento dell’iterabile e restituisce un nuovo iterabile contenente solo gli elementi per i quali la funzione restituisce un valore true
. L’esempio seguente filtra un elenco di valori interi all’interno di un determinato intervallo per restituire solo quelli pari:
def is_even(n):
return n%2 == 0
nums_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_list = filter(is_even, nums_list)
print(list(even_list))
Nel codice qui sopra, iniziamo definendo una funzione, is_even
, per calcolare un numero pari passato a tale funzione. Poi, creiamo un elenco di valori interi compresi tra 1 e 10 – nums_list
. Infine, definiamo una nuova lista, even_list
, che utilizza la funzione filter()
per applicare il metodo definito dall’utente alla lista originale e restituire solo gli elementi della lista pari. Ecco il risultato:
[2, 4, 6, 8, 10]
4. Map
Come filter()
, la funzione map()
di Python prende come argomenti un’iterabile e una funzione. Ma invece di restituire gli elementi dell’iterabile iniziale, restituisce una nuova iterabile contenente il risultato della funzione applicata a ciascun elemento della prima iterabile. Per elevare al quadrato un elenco di numeri interi, usiamo la funzione map()
:
my_list = [2, 4, 6, 8, 10]
square_numbers = map(lambda x: x ** 2, my_list)
print(list(square_numbers))
In questo codice, x
è l’iteratore che attraversa l’elenco e lo trasforma attraverso il calcolo del quadrato. La funzione map()
esegue questa operazione prendendo come argomento l’elenco originale e una funzione di mappatura. L’output è il seguente:
[4, 16, 36, 64, 100]
5. Sorted
La funzione sorted
ordina gli elementi di un dato iterabile in un ordine specifico (ascendente o discendente) e lo restituisce come elenco. Accetta un massimo di 3 parametri: iterable
, reverse
(opzionale) e key
(opzionale). reverse
ha come valore predefinito False
e, se impostato su True
, gli elementi vengono ordinati in ordine decrescente. key
è una funzione che calcola un valore per determinare l’ordine degli elementi di un iterabile e ha come valore predefinito None
.
Ecco un esempio di come possiamo applicare la funzione sorted
a diversi iterabili:
# set
py_set = {'e', 'a', 'u', 'o', 'i'}
print(sorted(py_set, reverse=True))
# dictionary
py_dict = {'e': 1, 'a': 2, 'u': 3, 'o': 4, 'i': 5}
print(sorted(py_dict, reverse=True))
# frozen set
frozen_set = frozenset(('e', 'a', 'u', 'o', 'i'))
print(sorted(frozen_set, reverse=True))
# string
string = "kinsta"
print(sorted(string))
# list
py_list = ['a', 'e', 'i', 'o', 'u']
print(py_list)
Si ottiene il seguente risultato:
['u', 'o', 'i', 'e', 'a']
['u', 'o', 'i', 'e', 'a']
['u', 'o', 'i', 'e', 'a']
['a', 'i', 'k', 'n', 's', 't']
['a', 'e', 'i', 'o', 'u']
Come gestire i casi limite e gli errori negli iterabili
I casi limite sono comuni in molti scenari di programmazione e devono essere previsti negli iterabili. Esploriamo alcune possibilità che potremmo incontrare.
1. Iterabili vuoti
Potremmo incontrare dei problemi quando un iterabile è vuoto, ma una logica di programmazione tenta di scorrerlo. Possiamo risolvere questo problema in modo programmatico per evitare inefficienze. Ecco un esempio che utilizza un’istruzione if not
per verificare se un elenco è vuoto:
fruits_list=[]
if not fruits_list:
print("The list is empty")
Questo è il risultato:
The list is empty
2. Iterabili annidati
Python supporta anche gli iterabili annidati, ovvero oggetti iterabili che contengono altri iterabili al loro interno. Ad esempio, possiamo avere un elenco di alimenti che contiene elenchi annidati di categorie di alimenti, come carne, verdure e cereali. Ecco come modellare uno scenario del genere utilizzando gli iterabili annidati:
food_list = [["kale", "broccoli", "ginger"], ["beef", "chicken", "tuna"], ["barley", "oats", "corn"]]
for inner_list in food_list:
for food in inner_list:
print(food)
Nel codice qui sopra, la variabile food_list
contiene tre elenchi annidati, che rappresentano diverse categorie di alimenti. Il ciclo esterno (for inner_list in food_list:
) itera attraverso l’elenco primario e il ciclo interno (for food in inner_list:
) itera attraverso ogni elenco annidato, stampando ogni alimento. L’output è il seguente:
kale
broccoli
ginger
beef
chicken
tuna
barley
oats
corn
3. Gestione delle eccezioni
In Python, gli iterabili supportano anche operazioni di gestione delle eccezioni. Ad esempio, potremmo iterare su una lista e incontrare un errore IndexError
. Questo errore significa che stiamo cercando di fare riferimento a un elemento che supera i limiti dell’iterabile. Ecco come gestire un’eccezione di questo tipo utilizzando un blocco try-except
:
fruits_list = ["apple", "mango", "orange", "pear"]
try:
print(fruits_list[5])
except IndexError:
print("The index specified is out of range.")
Nel codice qui sopra, l’iterabile fruits_list
contiene cinque elementi mappati dagli indici 0
e 5
nella collezione di liste. La frase try
contiene una funzione print
che tenta di visualizzare il valore all’indice 5
dell’iterabile, che non esiste. Viene eseguita la funzione except
clause, returning the associated error message. The console returns the error:
The index specified is out of range.
Riepilogo
Imparare a usare al meglio l’iterazione in Python è fondamentale per ottenere un codice efficiente e leggibile. Comprendere i vari modi per iterare su diverse strutture di dati, utilizzare le comprensioni, i generatori e sfruttare le funzioni integrate vi renderà dei programmatori Python esperti.
Sia che si lavori con liste, dizionari, stringhe o oggetti personalizzati, sapere come usare e manipolare gli iterabili è un’abilità indispensabile nella programmazione Python.
Quando avrete finito di costruire la vostra applicazione Python e vorrete ospitarla online, provate l’Hosting di Applicazioni di Kinsta. I primi 20 dollari ve li offriamo noi!
Ci siamo persi qualcosa in questa guida? Condividetelo nella sezione commenti qui sotto!
Lascia un commento