Tout comprendre sur yield en Python : le guide complet
Le mot-clé yield
en Python permet de créer ce que l’on appelle une fonction génératrice.
Contrairement à return
qui renvoie une valeur une fois pour toutes, yield
suspend l’exécution de la fonction et conserve son état pour reprendre là où elle s’était arrêtée.
Ce petit mécanisme rend yield
idéal pour :
- Itérer sur de grandes quantités de données ;
- Créer des flux de données paresseux (le fameux lazy-loading) ;
- Améliorer la performance mémoire.
En résumé
yield
transforme une fonction classique en générateur, capable de produire des valeurs au fil de l’eau.
Syntaxe de yield et exemple
Synaxe de yield
La syntaxe de yield
est extrêmement simple :
def ma_fonction():
yield valeur
Il s'utilise exactement comme avec le mot-clé return
! 😉
Chaque fois que l’exécution atteint le mot-clé yield
, elle renvoie une valeur à l'appelant, mais ne termine pas la fonction. À l’appel suivant, elle reprend juste après le yield
.
Une fonction contenant au moins un
yield
devient automatiquement un générateur.
Exemple d'utilisation de yield
Prenons un petit exemple pour mieux comprendre le fonctionnement de yield
!
Imaginons une pizzeria qui prépare des pizzas une par une. Chaque pizza est “yieldée” dès qu’elle est prête, au lieu d’attendre que toutes soient terminées.
def fabriquer_pizzas():
yield "🍕 Margherita prête !"
yield "🍕 Reine prête !"
yield "🍕 4 Fromages prête !"
for pizza in fabriquer_pizzas():
print(f"Commande envoyée : {pizza}")
Résultat :
Commande envoyée : 🍕 Margherita prête !
Commande envoyée : 🍕 Reine prête !
Commande envoyée : 🍕 4 Fromages prête !
Ce type d’approche est parfait pour simuler des systèmes en file d’attente, du streaming de données, ou encore de la production par lot. Chaque yield
permet d’envoyer une donnée dès qu’elle est disponible, sans bloquer l’exécution du reste du programme.
Comprendre les générateurs en Python
Fonction classique vs générateur : quelles différences ?
Une fonction classique exécute son code, retourne une valeur avec return
et se termine immédiatement.
Une fonction génératrice utilise yield
. Elle :
- Peut produire plusieurs valeurs successivement ;
- Ne termine pas son exécution à chaque
yield
; - Reprend là où elle s’était interrompue.
Prenons cet exemple comparatif :
# Fonction classique
def classique():
return [1, 2, 3]
# Générateur
def generateur():
yield 1
yield 2
yield 3
Le générateur ne crée pas une liste entière en mémoire, il envoie chaque valeur à la demande.
Un comportement "paresseux" (lazy)
Le mot-clé yield
permet une évaluation paresseuse : les valeurs ne sont calculées qu’au moment où elles sont demandées.
Cela permet de :
- Réduire la consommation mémoire ;
- Gérer des flux continus ou très larges (des milliers d’éléments) ;
- Améliorer les performances en streaming.
Pour mieux comprendre son fonctionnement, reprenons un exemple. Cette fois-ci avec un générateur de nombres infinis.
def nombres_infinis():
i = 1
while True:
yield i
i += 1
gen = nombres_infinis()
print(next(gen)) # 1
print(next(gen)) # 2
Cette fonction ne s’arrête jamais, mais ne consomme presque aucune mémoire ! 😬
Elle se souvient de son dernier résultat pour l'augmenter de un à chaque appel de fonction : c'est tout l'intérêt d'un générateur.
yield et yield from : différents mais complémentaires
En Python, le mot-clé yield
permet de produire des valeurs une par une dans une fonction génératrice.
Mais dans certains cas, lorsque cette fonction doit à son tour appeler un autre générateur, cela peut vite devenir verbeux et répétitif.
C’est là que yield from
entre en scène.
Utiliser yield from pour une délégation simplifiée
Avec yield from
, on peut déléguer directement l’itération à un sous-générateur ou à n’importe quel itérable (liste, tuple, etc).
Voici un petit exemple :
def fruits():
yield from ["🍎", "🍌", "🍓"]
def legumes():
yield from ["🥦", "🥕"]
def marche():
yield "Début du marché"
yield from fruits()
yield from legumes()
yield "Fin du marché"
for item in marche():
print(item)
Nous créons ici trois générateurs :
fruits
- contient les fruits du marché ;legumes
- contient les légumes ;marche
- contient le fonctionnement de notre marché (bon, évidemment, c'est un exemple 😉).
Voici son résultat :
Début du marché
🍎
🍌
🍓
🥦
🥕
Fin du marché
Chaque générateur est modulaire, et yield from
nous permet de les composer facilement sans alourdir la logique.
Finalement, ce qu'il faut retenir c'est que yield
est fait pour produire manuellement des valeurs.
De son côté, yield from
permet d'intégrer facilement d'autres générateurs, ce qui nous permet de décomposer notre code, pour le rendre plus maintenable.
Tableau récapitulatif
Récapitulons tout ceci dans un petit tableau.
Aspect | yield | yield from |
Produit une valeur unique | ✅ Oui | ❌ Non |
Délègue à un itérable | ❌ Nécessite une boucle | ✅ Oui |
Syntaxe compacte | ❌ Moins claire pour la délégation | ✅ Très lisible |
Utilisé pour | Générateurs simples | Sous-générateurs |
Questions fréquentes sur yield
Voici les questions les plus fréquentes quand on débute avec yield
en Python.
Quelle est la différence entre
yield
etreturn
?
return
termine la fonction. yield
suspend et reprend plus tard.
Peut-on faire un
break
dans unyield
?
Oui, comme dans n’importe quelle boucle.
Est-ce compatible avec
async
?
Non. Pour l’asynchrone, on utilise async def
et await
.
Peut-on imbriquer plusieurs
yield
?
Oui. Même dans des boucles et conditions imbriquées.
Où puis-je me former à Python ?
Sur une formation complète, comme la notre ! 😋