Un générateur est une fonction qui produit des valeurs une à la fois, à la demande. Au lieu de return, on utilise yield. Avantage majeur : pas besoin de tout charger en mémoire.
return → termine la fonction et renvoie une valeur (la fonction "finit")
yield → renvoie une valeur mais MET LA FONCTION EN PAUSE. À l'appel suivant, elle reprend là où elle s'était arrêtée.Une fonction qui contient yield est automatiquement un générateur.
def pairs_infinis():
n = 0
while True:
yield n
n += 2gen = pairs_infinis() # ne calcule rien, prépare le générateur
next(gen) # 0
next(gen) # 2
next(gen) # 4Ou avec une boucle
for _ in range(5):
print(next(gen))Si tu fais for v in pairs_infinis(): print(v) — boucle infinie ! Combine avec un break ou avec itertools.islice.
- Lazy evaluation : on ne calcule la valeur que quand on en a besoin.
- Mémoire : un générateur stocke seulement son état, pas TOUTES les valeurs.
- Possibilité de séquences infinies (impossibles en liste).Exemple : lire un gros fichier ligne par ligne sans tout charger :
def lire_lignes(chemin):
with open(chemin) as f:
for ligne in f:
yield ligne.strip()Forme courte avec des parenthèses (au lieu de crochets pour une list comprehension) :
carres = (x ** 2 for x in range(10)) # générateur
sum(x ** 2 for x in range(10)) # parenthèses optionnelles en argumentRègle : si tu vas itérer une seule fois et que la collection est grande, préfère un générateur à une liste.
Envie d'aller plus loin ? Découvrez nos formations certifiées Bac+2 à Bac+5 →