Pense-bête python : Generators

Les générateurs servent a simplifier la création d'iterateurs (iterator). Les itérateurs c'est le truc qui permet de faire des boucles for sur une variable, donc un iterateur c'est ce qui permet de créer des variables qui se comporte comme des listes par exemple. L'intéret du générateur sur l'itérateur est qu'il est beaucoup plus simple d'utilisation. Pour ce que j'en ai compris, sous le capot les générateurs sont une "surcouche" aux iterateurs et se reposent dessus pour être mis en oeuvre.

Une fonction qui génére un iterateur basique

def uneliste():
    yield 'un'
    yield 'deux'
    yield 'trois'

Résultat :

>>> for i in uneliste(): print (i)
... 
un
deux
trois
>>>

C'est l'instruction yield qui permet de renvoyer le résultat. La particularité de yield est de mettre en pause la fonction après avoir transmis la réponse et de reprendre l'exécution de la fonction à l'endroit où elle a été interrompue à chaque demande de valeur.Ici un exemple un peu plus utile :

def pairs(n):
    i = 0
    while i < n:
        yield i
        i += 2

Résultat :

>>> for i in pairs(10): print (i)
... 
0
2
4
6
8
>>>

Ca n'a l'air de rien, mais un autre intérêt des générateurs est la possibilité de générer des données à la volée et donc de ne pas avoir à stocker les résultats intermédiaire. Si j'avais utilisé une liste, j'aurais du préalablement calculer tous les nombres pair et les stocker dans la liste pour pouvoir itérer dessus.

Un générateur dans une classe

Cet exemple a pour seul intérêt d'exister pour ne pas avoir à chercher un exemple sur le net :) Il n'apporte rien de plus que ce qui a été décrit précédemment.

class IPList:
    def __init__(self):
        self.ipliste = []

    def Add(self,ip):
        self.ipliste.append(ip)

    def List(self):
        for i in self.ipliste:
            yield i+"/32"

ipl = IPList()
ipl.Add("192.168.0.1")
ipl.Add("192.168.0.4")
ipl.Add("192.168.0.10")

for i in ipl.List(): print (i)

Résultat :

matou@chihiro-pc:~/Travaux/PensebetePython$ ./generators.py 
192.168.0.1/32
192.168.0.4/32
192.168.0.10/32

Faire "tourner" un generateur pas à pas avec next

Bon, là tout de suite je ne vois pas une application concrète à utiliser ce mécanisme, mais comme cela peut-être utile pour la compréhension des coroutines, je me garde ça sous le coude.

>>> def tourne():
...     for i in range(40):
...         yield i
... 
>>> t = tourne()
>>> next(t)
0
>>> next(t)
1
>>> next(t)
2
>>> next(t)
3
>>>

Comments !

blogroll

social