Les Crash-Devs d'un Passionné

Les générateurs avec yield

/Catégorie/python

Temps de lecture : 2 minutes

Avant d'aborder les générateurs nous allons voir les itérateurs, car un générateur est un type d'itérateur. Un itérateur est une séquence que l'on peut appliquer sur une boucle for. Il implémente des fonctions next() et iter() pour parcourir les éléments

clipboard
Copier le code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
my_list = [1, 2, 3, 4]
print(type(my_list))

my_iter = iter(my_list)
print(my_iter)

# Extract the first element
print(next(my_iter))

# Extract the second element
print(my_iter.next()) # or my_iter.__next__() 

for i in my_iter:
  print i


> <type 'list'>
> <listiterator object at 0x0000000004023358>
> 1
> 2
> 3
> 4

Après ce petit rappel on attaque…

Le yield est une instruction permettant de retourner un générateur, c'est-à-dire un objet python permettant de gérer plus facilement des itérateurs (chaine de caractères, liste, fichier… qui possède un index)

Un générateur retourne la valeur à la volée et ne stock rien en mémoire contrairement à un itérateur.

Un générateur ne s'exécute pas tant que l'on n'itère pas dessus.

On retrouve cette spécification dans la PEP 255

À chaque fois que python rencontre un yield il retourne la valeur du générateur.

clipboard
Copier le code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
def create_generator() :
  my_list = range(3)
  for i in my_list:
    yield i*i

generator = create_generator()
print(generator) # It's a generator

for i in generator:
  print(i)


> <generator object create_generator at 0x00000000048BCFC0>
> 0
> 1
> 4

Depuis la version python 3.3 décrit dans la PEP 380 il est possible d'utiliser

yield from
dans le but de s'affranchir d'une boucle
for

clipboard
Copier le code
1
2
3
4
5
6
7
8
9
def create_generator() :
    yield from map(lambda i: i*i, range(3))

for v in create_generator():
    print(v)

> 0
> 1
> 4

Il existe une librairie qui permet de gérer les itérateurs : itertools

Elle contient une liste de fonction utiles qui permet de faire des traitements sur des séquences et de retourner un itérateur

Voici quelques exemples

clipboard
Copier le code
1
2
3
4
5
6
7
8
9
import itertools

# Return iterator with all combinaisons on 2 elements
for x in itertools.permutations(['a', 'b', 'c'], 2):
  print(x)

# Return iterator after Filter on list apply 
for x in itertools.ifilter(lambda t: t > 2, [1, 2, 3, 4, 5]):
  print(x)

Et voilà rien de bien compliqué, maintenant il vous reste plus qu'à l'utiliser dans vos scripts !