ConsigneCréez un générateur de nombres pairs infinis
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érateurnext(gen) # 0next(gen) # 2next(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érateursum(x ** 2 for x in range(10)) # parenthèses optionnelles iciLes parenthèses ne sont optionnelles que si la generator expression est le seul argument de l'appel. Dès qu'il y en a un second, elles redeviennent obligatoires, sinon Python refuse de compiler :
sum(x ** 2 for x in range(10), 0) # SyntaxErrorsum((x ** 2 for x in range(10)), 0) # correctRè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 →