Générateurs Python : itération efficace et cas d'utilisation avancés
Générateurs Python
Découvrez comment les générateurs Python simplifient l'itération, réduisent le code boilerplate et améliorent l'utilisation mémoire comparé aux itérateurs traditionnels.
Que sont les générateurs ?
Construire un itérateur personnalisé en Python nécessite généralement une classe qui implémente __iter__() et __next__(), gère l'état interne et lève StopIteration quand fini. Les générateurs éliminent ce boilerplate en vous permettant d'écrire une simple fonction qui produit des valeurs une à la fois.
En résumé, un générateur est une fonction qui retourne un itérateur. Le corps de la fonction s'exécute paresseusement, se mettant en pause après chaque yield et reprenant aux appels subséquents.
Créer des générateurs en Python
Définir un générateur est aussi simple qu'écrire une fonction normale et remplacer un return par yield :
def mon_gen():
n = 1
print('Ceci est affiché en premier')
yield n
n += 1
print('Ceci est affiché en second')
yield n
n += 1
print('Ceci est affiché en dernier')
yield n
L'appel de mon_gen() retourne un itérateur qui commence à s'exécuter seulement quand next() est appelé.
a = mon_gen()
next(a) # affiche le premier message et retourne 1
next(a) # affiche le second message et retourne 2
next(a) # affiche le dernier message et retourne 3
next(a) # lève StopIteration
Les variables locales persistent entre les yields, mais le générateur ne peut être itéré qu'une seule fois. Pour recommencer, créez une nouvelle instance.
Puisqu'un générateur est un itérateur, vous pouvez boucler dessus directement :
for item in mon_gen():
print(item)
Motifs courants de générateurs
Inverser une chaîne
def inverser_chaine(s):
for i in range(len(s)-1, -1, -1):
yield s[i]
for char in inverser_chaine('bonjour'):
print(char)
Fonctionne avec n'importe quel itérable (liste, tuple, etc.).
Expressions de générateur
Des générateurs anonymes peuvent être créés avec des parenthèses, similaires aux compréhensions de liste :
ma_liste = [1, 3, 6, 10]
# Compréhension de liste
carres_liste = [x**2 for x in ma_liste]
# Expression de générateur
carres_gen = (x**2 for x in ma_liste)
print(carres_liste)
print(carres_gen)
Le générateur produit les valeurs à la demande :
a = (x**2 for x in ma_liste)
print(next(a)) # 1
print(next(a)) # 9
print(next(a)) # 36
print(next(a)) # 100
next(a) # StopIteration
Les expressions de générateur peuvent être passées directement à des fonctions comme sum ou max sans les parenthèses entourantes.
Pourquoi utiliser les générateurs ?
- Implémentation concise : Remplace les classes d'itérateurs verbeuses par quelques lignes de code.
- Efficacité mémoire : Produit un élément à la fois, idéal pour les séquences grandes ou infinies.
- Flux infinis : Représente des sources de données sans fin (ex. :
while True: yield). - Composition de pipelines : Chaîne plusieurs générateurs pour un traitement de données propre et lisible.
Exemple : Puissance de deux
def puissance_deux_gen(max_n=0):
n = 0
while n < max_n:
yield 2 ** n
n += 1
Exemple : Somme des carrés des nombres de Fibonacci
def nombres_fibonacci(count):
a, b = 0, 1
for _ in range(count):
a, b = b, a + b
yield a
def carres(nums):
for n in nums:
yield n ** 2
print(sum(carres(nombres_fibonacci(10)))) # 4895
Les générateurs permettent un code élégant, efficace et maintenable pour une large gamme de scénarios d'itération.
Python
- Maîtriser les opérateurs Python : Guide complet
- Maîtriser les arguments de fonctions Python : Positionnels, nommés et paramètres par défaut
- Maîtriser les dictionnaires Python : création, manipulation et techniques avancées
- Générateurs Python : itération efficace et cas d'utilisation avancés
- Les fermetures Python expliquées : comment les fonctions imbriquées capturent les variables
- Maîtriser les décorateurs Python : améliorer les fonctions avec des techniques expertes
- Maîtriser les fonctions lambda Python : exemples pratiques et bonnes pratiques
- Fonction Python abs() : calculer les valeurs absolues pour nombres et nombres complexes
- Fonction Python round() expliquée avec exemples pratiques