Différencier l'itérateur et le générateur en Python
Les itérateurs et les générateurs nous aident à générer une sortie ou à traiter du code de manière itérative, un bit à la fois. Dans cet article, nous apprendrons quelques différences fondamentales entre les itérateurs et les générateurs de Python avec un exemple simple.
Itérateur en Python
Les fonctionnalités de base d’un itérateur sont les suivantes :
- Un itérateur est un objet créé à l’aide d’une classe qui implémente le protocole d’itérateur. Cela signifie que la classe a des méthodes
__iter__
et__next__
définies. - La méthode
__next__
utilise l’instructionreturn
pour renvoyer une valeur. Comme l’instructionreturn
doit être la dernière ligne de cette méthode, nous devons mettre à jour la variable à utiliser lors de la prochaine exécution de__next__
avant l’instructionreturn
.
Dans le cas le plus simple, on va regarder, __iter__
renvoie self
.
Générateur en Python
Les caractéristiques de base d’un générateur sont les suivantes :
- Un générateur est une fonction.
- Une fonction génératrice utilise le mot-clé
yield
au lieu du mot-cléreturn
.
2.1 Le mot-cléyield
donne une valeur et suspend l’exécution de la fonction.
2.2 L’appel suivant ànext()
reprend l’exécution du code après l’instructionyield
.
Une fonction de générateur nous permet de créer un itérateur de générateur sans tout le code supplémentaire requis lors de la création d’un itérateur à l’aide d’une classe.
Exemples d’itérateur et de générateur en Python
Les deux exemples suivants mettent en évidence les points mentionnés dans les deux sections précédentes. Les deux exemples illustrent comment générer des carrés d’entiers, en commençant par 1.
Le premier exemple montre comment cela se fait à l’aide d’un itérateur. Le deuxième exemple montre un code équivalent utilisant un générateur.
Exemple de code pour l’itérateur :
# ITERATOR (Class)
class squares(object):
def __init__(self, num1):
self.nxt_sq_of = 1
self.lim = num1
def __iter__(self):
return self
def __next__(self):
if self.nxt_sq_of <= self.lim:
ret_sq_of = self.nxt_sq_of
self.nxt_sq_of += 1
return ret_sq_of * ret_sq_of
else:
raise StopIteration
# Iterator Object
a = squares(6)
# Next value of the iterator.
next(a)
next(a)
next(a)
next(a)
next(a)
next(a)
next(a)
next(a)
# Using the iterator in a loop.
a1 = squares(6)
while True:
print(next(a1))
Production:
next(a)
Out[3]: 1
next(a)
Out[4]: 4
next(a)
Out[5]: 9
next(a)
Out[6]: 16
next(a)
Out[7]: 25
next(a)
Out[8]: 36
next(a)
Traceback (most recent call last):
File "<ipython-input-9-15841f3f11d4>", line 1, in <module>
next(a)
File "<ipython-input-1-9dbe8e565876>", line 17, in __next__
raise StopIteration
StopIteration
Exemple de code pour le générateur :
# GENERATOR FUNCTION
def gen_squares(num2):
i = 1
while i <= num2:
yield i * i
i += 1
# Generator iterator.
b = gen_squares(5)
# Next yield of the generator iterator.
next(b)
next(b)
next(b)
next(b)
next(b)
next(b)
Production:
next(b)
Out[3]: 1
next(b)
Out[4]: 4
next(b)
Out[5]: 9
next(b)
Out[6]: 16
next(b)
Out[7]: 25
next(b)
Traceback (most recent call last):
File "<ipython-input-8-adb3e17b0219>", line 1, in <module>
next(b)
StopIteration
Conclusion
Nous constatons que les générateurs de Python nous permettent d’écrire du code concis pour créer un itérateur de générateur.
Les itérateurs, en revanche, sont beaucoup plus puissants car ils permettent au programmeur d’écrire du code personnalisé pour la méthode __iter__
.
Pour plus de détails, reportez-vous à ce qui suit.
- Article Wiki Python pour générateurs.
- Article Wiki Python pour itérateurs.