Les itérateurs et les générateurs sont à la base du traitement efficace des séquences en Python. Historiquement, Python a cherché à simplifier le travail avec des flux de données et à éviter de stocker de grandes collections en mémoire. Au départ, le support des itérateurs a été introduit via les protocoles __iter__ et __next__, puis les générateurs ont permis de créer de simples itérateurs à l'aide de constructions basées sur yield.
Problème : il est souvent nécessaire de traiter de grandes quantités de données (par exemple, le streaming à partir d'un fichier ou d'une base de données), ce qui n'est pas pratique ni efficace si l'on charge tout en mémoire à la fois. Les fonctions ordinaires renvoient tous les résultats à la fois, et créer ses propres itérateurs via des classes est souvent trop encombrant pour des cas simples.
Solution : le mécanisme yield permet d'organiser une génération de données "paresseuse". La fonction génératrice ne retourne pas une liste ou une autre collection, mais renvoie un objet générateur — un itérateur qui calcule les valeurs au fur et à mesure de la demande.
Exemple de code :
# Générateur simple def countdown(n): while n > 0: yield n n -= 1 for i in countdown(3): print(i) # 3, 2, 1
Caractéristiques clés :
Peut-on utiliser return et yield dans une même fonction ?
Oui, mais return dans un générateur termine l'itération (lève StopIteration), tandis que yield peut être utilisé autant de fois que nécessaire.
def example(): yield 1 return # StopIteration
Pourquoi un générateur ne peut-il pas être "redémarré" après avoir terminé ?
Un générateur, après avoir épuisé les itérations (StopIteration), ne peut pas être redémarré, il doit être créé à nouveau.
gen = countdown(2) list(gen) # [2, 1] list(gen) # [] (le générateur est déjà épuisé)
Quelle est la différence entre un générateur et un itérateur ?
Un générateur est un cas particulier d'itérateur ; tout objet avec les méthodes iter et next est un itérateur, mais un générateur est créé via une fonction avec yield.
Un développeur a écrit une fonction qui charge un million de lignes d'un fichier en mémoire via list(fd) pour analyse. Cela a conduit à un débordement de mémoire sur le serveur.
Avantages :
Inconvénients :
Utilisation d'un générateur pour lire un fichier ligne par ligne et analyser les données à la volée avec yield.
Avantages :
Inconvénients :