Itérateurs et générateurs Python3


Iterator

L'itération est l'une des fonctionnalités les plus puissantes de Python, et un moyen d'accéder aux éléments d'une collection.

Un itérateur est un objet qui peut mémoriser la position du parcours.

L'objet itérateur commence à accéder à partir du premier élément de la collection jusqu'à ce que tous les éléments aient été accédés. Les itérateurs ne peuvent aller que vers l'avant, pas vers l'arrière.

Les itérateurs ont deux méthodes de base :iter()etnext()。

Les chaînes de caractères, les listes ou les objets de type tuple peuvent tous être utilisés pour créer des itérateurs :

Exemple (Python 3.0+)

>>> liste=[1,2,3,4]
>>> it = iter(list)    # Créer un objet itérateur
>>> print (next(it))   # Afficher l'élément suivant de l'itérateur
1
>>> print (next(it))
2
>>>

Les objets itérateurs peuvent être parcourus à l'aide d'une instruction for classique :

Exemple (Python 3.0+)

#!/usr/bin/python3 list=[1,2,3,4] it = iter(list) # Créer un objet itérateur for x in it: print (x, end=" ")

L'exécution du programme ci-dessus produit la sortie suivante :

1 2 3 4

Vous pouvez également utiliser la fonction next() :

Exemple (Python 3.0+)

#!/usr/bin/python3 import sys # Importer le module sys list=[1,2,3,4] it = iter(list) # Créer un objet itérateur while True: try: print (next(it)) except StopIteration: sys.exit()

L'exécution du programme ci-dessus produit la sortie suivante :

1
2
3
4

Créer un itérateur

Pour utiliser une classe comme itérateur, vous devez implémenter deux méthodes dans la classe : __iter__() et __next__().

Si vous comprenez déjà la programmation orientée objet, vous savez que les classes ont un constructeur. Le constructeur de Python est __init__(), qui est exécuté lorsque l'objet est initialisé.

Pour plus d'informations, consultez :Programmation orientée objet en Python3

La méthode __iter__() renvoie un objet itérateur spécial qui implémente la méthode __next__() et signale la fin de l'itération au moyen d'une exception StopIteration.

La méthode __next__() (next() dans Python 2) renvoie l'objet itérateur suivant.

Créez un itérateur qui renvoie des nombres, en commençant par une valeur initiale de 1 et en incrémentant de 1 à chaque étape :

Exemple (Python 3.0+)

class MyNumbers: def __iter__(self): self.a = 1 return self def __next__(self): x = self.a self.a += 1 return x myclass = MyNumbers() myiter = iter(myclass) print(next(myiter)) print(next(myiter)) print(next(myiter)) print(next(myiter)) print(next(myiter))

La sortie après exécution est :

1
2
3
4
5

StopIteration

L'exception StopIteration est utilisée pour signaler la fin de l'itération et éviter les boucles infinies. Dans la méthode __next__(), nous pouvons le configurer pour lever l'exception StopIteration après avoir effectué un nombre spécifié de boucles afin de mettre fin à l'itération.

Arrêter l'exécution après 20 itérations :

Exemple (Python 3.0+)

class MyNumbers: def __iter__(self): self.a = 1 return self def __next__(self): if self.a <= 20: x = self.a self.a += 1 return x else: raise StopIteration myclass = MyNumbers() myiter = iter(myclass) for x in myiter: print(x)

La sortie après exécution est :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Generator

En Python, les fonctions qui utilisent `yield`yieldsont appelées générateurs (generator).

yield`yield` est un mot-clé utilisé pour définir des fonctions génératrices. Une fonction génératrice est un type spécial de fonction qui peut produire des valeurs étape par étape pendant l'itération, plutôt que de renvoyer tous les résultats d'un coup.

Contrairement aux fonctions ordinaires, un générateur est une fonction qui renvoie un itérateur et ne peut être utilisé que pour des opérations d'itération. En termes simples, un générateur est un itérateur.

Lors de l'utilisation de `yield` dans une fonction génératriceyieldinstruction, l'exécution de la fonction se met en pause, etyieldl'expression après `yield` est renvoyée comme valeur de l'itération courante.

Ensuite, chaque fois que la méthodenext()`__next__()` du générateur est appelée ouforune boucle `for` est utilisée pour l'itération, la fonction reprend son exécution à l'endroit où elle s'était arrêtée jusqu'à ce qu'elle rencontre un autreyield`yield` instruction. De cette façon, la fonction génératrice peut produire des valeurs étape par étape, sans avoir besoin de calculer et de renvoyer tous les résultats d'un coup.

Appeler une fonction génératrice renvoie un objet itérateur.

Ce qui suit est un exemple simple qui démontre l'utilisation des fonctions génératrices :

Exemple

def countdown(n): while n > 0: yield n n -= 1 # Créer un objet générateur generator = countdown(5) # Obtenir des valeurs en itérant sur le générateur print(next(generator)) # Sortie : 5 print(next(generator)) # Sortie : 4 print(next(generator)) # Sortie : 3 # Utiliser une boucle for pour parcourir le générateur for value in generator: print(value) # Sortie : 2 1

Dans l'exemple ci-dessus,countdownest une fonction génératrice. Elle utilise des instructions yield pour produire les nombres du compte à rebours de n à 1. Chaque fois qu'une instruction yield est exécutée, la fonction renvoie la valeur actuelle du compte à rebours et, lors de l'appel suivant, reprend l'exécution là où elle s'était arrêtée la dernière fois.

En créant un objet générateur et en utilisant la fonction next() ou une boucle for pour parcourir le générateur, nous pouvons obtenir progressivement les valeurs produites par la fonction génératrice. Dans cet exemple, nous utilisons d'abord la fonction next() pour obtenir les trois premières valeurs de compte à rebours, puis nous utilisons une boucle for pour obtenir les deux restantes.

L'avantage des fonctions génératrices est qu'elles peuvent produire des valeurs à la demande, évitant de générer une grande quantité de données en une seule fois et d'occuper une grande quantité de mémoire. De plus, les générateurs peuvent fonctionner de manière transparente avec d'autres outils d'itération (comme les boucles for), offrant une méthode d'itération concise et efficace.

L'exécution du programme ci-dessus produit la sortie suivante :

5
4
3
2
1

L'exemple suivant utilise yield pour implémenter la suite de Fibonacci :

Exemple (Python 3.0+)

#!/usr/bin/python3 import sys def fibonacci(n): # Fonction génératrice - Fibonacci a, b, counter = 0, 1, 0 while True: if (counter > n): return yield a a, b = b, a + b counter += 1 f = fibonacci(10) # f est un itérateur, renvoyé et généré par le générateur while True: try: print (next(f), end=" ") except StopIteration: sys.exit()

L'exécution du programme ci-dessus produit la sortie suivante :

0 1 1 2 3 5 8 13 21 34 55
Autres extensions