11. Itérateurs et Générateurs
Protocole d’itération,
iter(),next(),yield,yield from,itertools.
11.1 Protocole d’itération
Un itérable implémente __iter__() → retourne un itérateur.
Un itérateur implémente __next__() → élément suivant ou StopIteration.
class Compteur:
def __init__(self, max: int):
self.max = max
self.n = 0
def __iter__(self):
return self # l'itérateur est lui-même
def __next__(self) -> int:
if self.n >= self.max:
raise StopIteration
valeur = self.n
self.n += 1
return valeurfor x in Compteur(3):
print(x) # 0, 1, 211.2 iter() et next()
L = [1, 2, 3]
it = iter(L) # itérateur
next(it) # 1
next(it) # 2
next(it) # 3
next(it) # StopIteration11.3 Générateurs
Fonction qui utilise yield au lieu de return :
def compteur(max: int):
n = 0
while n < max:
yield n
n += 1for x in compteur(3):
print(x) # 0, 1, 2Avantage : paresse (lazy), pas de stockage en mémoire.
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
[next(fib) for _ in range(10)] # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]11.4 Générateurs et mémoire
Comparaison :
# Liste complète en mémoire (100M éléments) — plante
# cubes = [x**3 for x in range(100_000_000)]
# Générateur paresseux — ok
cubes = (x**3 for x in range(100_000_000)) # generator expression
next(cubes), next(cubes) # 0, 111.5 yield from
Délègue à un sous-itérateur :
def chaine(*iterables):
for it in iterables:
yield from it
list(chaine([1, 2], [3, 4])) # [1, 2, 3, 4]11.6 send() et throw()
Les générateurs peuvent recevoir des valeurs :
def accumulateur():
total = 0
while True:
valeur = yield total
if valeur is None:
break
total += valeur
acc = accumulateur()
next(acc) # initialiser → 0
acc.send(10) # 10
acc.send(5) # 15
acc.send(None) # StopIteration11.7 itertools
Outils de compositions d’itérateurs :
from itertools import (
chain, cycle, repeat, count,
accumulate, product, permutations, combinations,
islice, takewhile, groupby,
)
chain([1, 2], [3, 4]) # 1, 2, 3, 4
cycle("AB") # A, B, A, B, ...
repeat(10, 3) # 10, 10, 10
count(5, 2) # 5, 7, 9, 11, ...
accumulate([1, 2, 3, 4]) # 1, 3, 6, 10
product("AB", repeat=2) # AA, AB, BA, BB
permutations("ABC", 2) # AB, AC, BA, BC, CA, CB
combinations("ABC", 2) # AB, AC, BC
islice(count(), 10) # 5 1ers éléments