Capitolo 10: Iteratori, Generatori & Comprensioni

Approfondisci il protocollo di iterazione di Python, crea generatori per valutazione pigra e usa comprensioni per trasformazioni concise dei dati.

Scarica chapter10.py

Obiettivi

1. Iteratori & Protocollo di Iterazione

Qualsiasi oggetto che implementa __iter__() e __next__() è un iteratore:

# le liste sono iterable, non iteratori
lst = [1,2,3]
it = iter(lst)         # ottiene l'iteratore
print(next(it))        # 1
print(next(it))        # 2
# StopIteration quando esaurito

Classe iteratore personalizzata:

class Counter:
    def __init__(self, limit):
        self.limit = limit
        self.current = 0
    def __iter__(self):
        return self
    def __next__(self):
        if self.current >= self.limit:
            raise StopIteration
        val = self.current
        self.current += 1
        return val

for i in Counter(3):
    print(i)  # 0, 1, 2

2. Funzioni Generatrici

Usa yield per produrre una sequenza pigramente:

def fib(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

for num in fib(5):
    print(num)  # 0, 1, 1, 2, 3

I generatori mantengono automaticamente lo stato e sollevano StopIteration al termine.

3. Espressioni Generatrici

Sintassi compatta per creare generatori:

# generatore di quadrati
squares = (x*x for x in range(10))
print(next(squares))   # 0
for sq in squares:
    print(sq)

4. Comprensioni

a) List Comprehensions

# quadrati dei numeri pari da 0 a 9
even_squares = [x*x for x in range(10) if x % 2 == 0]

b) Dict Comprehensions

# mappa numero al suo quadrato
sq_map = {x: x*x for x in range(5)}

c) Set Comprehensions

# lettere iniziali uniche
names = ["Alice","Bob","Anna"]
first_letters = {name[0] for name in names}

Esercizi

  1. Implementa una classe iteratore Fibonacci che generi numeri di Fibonacci fino a n.
  2. Scrivi un generatore primes() che produca numeri primi indefinitamente.
  3. Usa un’espressione generatrice per calcolare pigramente la somma dei quadrati da 1 a 100.
  4. Appiattisci una lista annidata (ad esempio [[1,2],[3,4]]) usando una comprehensions di lista annidata.
  5. Data una mapping dict, scrivi una dict comprehension per invertire chiavi e valori.