Appeler une fonction avec yield ne l'exécute pas. Ça fabrique un générateur.Calling a function with yield doesn't run it. It builds a generator.
Le numéro précédent a montré l'itérateur écrit à la main : une classe, un __iter__ qui retourne self, un __next__ qui avance un état stocké dans des attributs. Le générateur est un raccourci syntaxique pour exactement ce patron — mais un raccourci qui cache une mécanique déroutante. compte(3) ne lance rien : aucune ligne du corps ne s'exécute, print("démarrage") ne s'affiche pas. L'appel retourne immédiatement un objet générateur, un itérateur en puissance. Le corps ne commence à tourner qu'au premier next() — et s'arrête, gelé, à chaque yield, pour reprendre exactement là au prochain appel.The previous issue showed the hand-written iterator: a class, an __iter__ returning self, a __next__ advancing state stored in attributes. The generator is syntactic shorthand for exactly that pattern — but a shorthand that hides a disorienting mechanic. compte(3) launches nothing: no line of the body runs, print("démarrage") doesn't print. The call immediately returns a generator object, an iterator waiting to happen. The body only starts running at the first next() — and stops, frozen, at every yield, to resume exactly there on the next call.
def compte(fin): print("démarrage") # on s'attend à voir ça tout de suite... n = 0 while n < fin: n += 1 yield n # <- suspend ici, renvoie n, attend le prochain next() print("terminé") g = compte(3) print("g créé") # affiché AVANT "démarrage" ! print(next(g)) # affiche "démarrage", puis 1 print(next(g)) # 2 — reprend juste après le yield précédent print(next(g)) # 3 print(next(g)) # affiche "terminé", puis StopIteration
Face à une fonction contenant yield, ne demande jamais « que fait-elle ? » mais « à quel moment, exactement, chaque ligne s'exécute-t-elle ? » L'appel construit ; seul next() avance.Facing a function with yield, never ask "what does it do?" but "exactly when does each line run?" The call builds; only next() advances.
return quitte la fonction et efface son état. yield le fige : son cadre d'exécution — détaché de la pile pendant la pause —, les variables locales, la position dans la boucle restent en mémoire, prêts à reprendre. C'est une pause, pas une sortie.return exits the function and erases its state. yield freezes it: its frame — detached from the stack while paused —, local variables, position in the loop stay in memory, ready to resume. It's a pause, not an exit.