🐍 PyTutos

Les générateurs (yield)

Produis des valeurs à la volée sans tout stocker en mémoire.

⏱ 12 minutes 📂 avance #avance #generateurs #yield #iterateurs

Les générateurs

Un générateur est une fonction qui produit des valeurs une à une, au fur et à mesure qu'on les demande, sans tout stocker en mémoire.

La différence avec une fonction normale

Fonction classique (tout en mémoire) :

def carres(n):
    resultat = []
    for i in range(n):
        resultat.append(i * i)
    return resultat   # une grosse liste

for c in carres(1_000_000):
    print(c)   # mais on a créé 1 million de carrés en mémoire

Générateur (à la volée) :

def carres(n):
    for i in range(n):
        yield i * i   # ← yield, pas return !

for c in carres(1_000_000):
    print(c)   # produit un carré à chaque tour, rien stocké

Comment ça marche ?

yield met la fonction en pause et renvoie une valeur. Au prochain appel (par next() ou la boucle for), elle reprend où elle s'était arrêtée.

def compte_jusqua(n):
    print("démarrage")
    for i in range(n):
        yield i
        print(f"après yield {i}")
    print("fin")

g = compte_jusqua(3)
print(next(g))   # démarrage     puis 0
print(next(g))   # après yield 0 puis 1
print(next(g))   # après yield 1 puis 2

Exemple : la suite de Fibonacci

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

gen = fibonacci()
for _ in range(10):
    print(next(gen), end=" ")
# 0 1 1 2 3 5 8 13 21 34

Note : ce générateur est infini mais ça ne plante pas, parce qu'on en prend juste 10.

Expression génératrice (one-liner)

Comme une compréhension mais avec () au lieu de [] :

carres = (x*x for x in range(1_000_000))   # rien en mémoire
print(sum(carres))   # 333332833333500000

Cas réels

  • Lire un gros fichier ligne par ligne : le fichier est déjà un générateur
  • Pagination d'une API : produire la page suivante à la demande
  • Flux infini : random, capteurs, événements…
def lire_fichier(chemin):
    with open(chemin) as f:
        for ligne in f:
            yield ligne.strip()

for ligne in lire_fichier("gros.txt"):
    if "ERREUR" in ligne:
        print(ligne)

💡 Règle d'or : si tu vas itérer une seule fois et que la liste pourrait être grosse → utilise un générateur.

🧪 Quiz de validation

Réponds à toutes les questions. Il faut 70% de bonnes réponses pour valider le tuto !

🔒 Tu dois être connecté pour passer le quiz.