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 valeur
for x in Compteur(3):
    print(x)  # 0, 1, 2

11.2 iter() et next()

L = [1, 2, 3]
it = iter(L)         # itérateur
next(it)             # 1
next(it)             # 2
next(it)             # 3
next(it)             # StopIteration

11.3 Générateurs

Fonction qui utilise yield au lieu de return :

def compteur(max: int):
    n = 0
    while n < max:
        yield n
        n += 1
for x in compteur(3):
    print(x)  # 0, 1, 2

Avantage : 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, 1

11.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)     # StopIteration

11.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

🔗 ← Retour au cours · ← précédent · Suivant →