En utilisant yield
, une fonction devient un générateur. Un générateur est un type spécialisé d'itérateur. for
boucle toujours sur des objets itérables, prenant chaque élément tour à tour et l'assignant au(x) nom(s) que vous avez listé(s).
spinning_cursor()
renvoie un générateur, le code à l'intérieur de spinning_cursor()
n'est pas exécuté tant que vous ne commencez pas à itérer sur le générateur. Itérer sur un générateur signifie que le code dans la fonction est exécuté jusqu'à ce qu'il rencontre une instruction yield
, à ce moment-là le résultat de l'expression est retourné comme valeur suivante et l'exécution est à nouveau en pause.
La boucle for
fait exactement cela, elle appellera l'équivalent de next()
sur le générateur, jusqu'à ce que le générateur signale qu'il a terminé en levant StopIteration
(ce qui se produit lorsque la fonction se termine). Chaque valeur de retour de next()
est assignée, tour à tour, à c
.
Vous pouvez voir cela en créant le générateur dans l'invite Python :
>>> def spinning_cursor():
... cursor='/-\|'
... i = 0
... while 1:
... yield cursor[i]
... i = (i + 1) % len(cursor)
...
>>> sc = spinning_cursor()
>>> sc
>>> next(sc)
'/'
>>> next(sc)
'-'
>>> next(sc)
'\\'
>>> next(sc)
'|'
Ce générateur spécifique ne se termine jamais, donc StopIteration
n'est jamais levée et la boucle for
continuera indéfiniment à moins que vous ne tuiez le script.
Une alternative bien plus ennuyeuse (mais plus efficace) serait d'utiliser itertools.cycle()
:
from itertools import cycle
spinning_cursor = cycle('/-\|')