Thématiques principales

mardi 5 mars 2019

Python : Listes et générateurs

Aujourd'hui nous allons mettre Java un peu de coté et revenir pour ces prochaines semaine aux technologies et connaissances nécessaires au Machine Learning.

Nous avions déjà fait quelques articles, sur les réseaux de neurones avec du Java, du python etc... Du coup comme nous avons déjà bien traité de Java durant ces derniers mois, je vous propose de revenir maintenant sur le langage python.

Alors bien sur ce n'est pas en un article que l'on fera le tour de ce langage qui est tout aussi complexe que Java et de tout son eco-système. Mais on peut malgré tout tenter d'en survoler les mécanismes essentiels afin de pouvoir l'exploiter au mieux. Alors on ne va pas refaire non plus ici un cours de syntaxe mais regarder comment l'utiliser: voir un peu les listes en compréhension, l’intérêt des décorateurs, faire un petit tour du coté des générateurs et bien sur jouer avec les classes et méta-classes etc...



Normalement, a l'issu de cet article (ou de ces articles car potentiellement il pourrait y en avoir plusieurs) tous ces concepts seront devenus familier et fautes peut être de savoir les utiliser a la volée dans vos projet, leur découvertes au détour d'un dépôt github ne devraient plus être un obstacle.

Bien commençons en allant au plus simple. alors pas trop quand même car si vous vous rappelez, dans l'article sur la manipulation des données en python, nous avions fait déjà le tour des variables, tuples, listes et dictionnaires. Donc si besoin, je vous invite a retourner consulter celui ci [manip-data].

On va quand même reprendre la définition de la liste en compréhension dont le principe est de proposer une fonction décrivant le contenu de la liste sur une certaine plage de donnée avec potentiellement divers filtres.


maListe=[ x for x in range(0,10) ]
maListe.extend([ x for x in range(10,20) ])
print(maListe)


Dans tout langage, on veut pouvoir manipuler ses listes et surtout itérer dessus, généralement on utilise le pattern iterateur. Je ne reviens pas dessus [iterateur] puisque nous l'avons déjà expliquer cependant avec python, on sort un peu du cadre.

En effet, outre le cas de l'iterateur, python a eut la brillante idée au travers de la surcharge de fonctions attendues de faciliter l’implémentation et l'utilisation de certains pattern (entre autre l'iterateur, vous l'aurez deviné...)

Entre autre donc pour faire un iterateur en python, il vous suffit donc de surcharger (enfin pas vraiment car celles ci ne sont pas présentes initialement en fait) deux méthodes:
  • __iter__
  • __next__
Par exemple:


class ObjetIterable():
    
    def __init__(self,liste):
        self.index=0
        self.liste=liste
        
    def __iter__(self):
        return self
        
    def __next__(self):
        if(self.index == len(self.liste)):
            raise StopIteration
        data=self.liste[self.index]
        self.index+=1;
        return data
        
l=[0,1,2,3,4]

for i in ObjetIterable(l):
    print(i)


Ainsi un objet issu de l'instanciation de ObjetIterable pourra être utiliser pour passer en revue les éléments de la liste l.

Bien sur ici l'utilisation de notre iterateur a peu d’intérêt puisque faisant le boulot de l'iterateur par défaut de la liste cependant dans le cas ou nous aurions besoin de construire des structures de données un peu spéciale, il sera intéressant de pouvoir parcourir les éléments a notre facon.

Il nous reste enfin une dernière manière de manipuler les listes : en les générant. Les générer? oui il est possible de construire des listes a la volée a l'aide de ce que l'on appelle les générateurs.

Ces derniers fonctionnent grâce au mot clef yield qui fonctionne comme un return mais sans faire le break de la fonction permettant de la poursuivre... étrange dis comme ça, car on ne rencontre pas souvent ce genre de procéder. Voici un exemple:


def binaryRange(min,max):
    x=min
    y=max
    print("first yield {0} {1}".format(x,y))
    yield (x,y)
    while (x<max or y>min):
        x+=1
        y-=1
        print("other yield {0} {1}".format(x,y))
        yield (x,y)
    
maListe=[ x*y for x,y in binaryRange(0,10) ]
print(maListe)


Donc voila, un générateur qui retourne une liste de tuple a deux éléments dont l'un est incrémenté et l'autre décrémenté mais bien sur l'on peut créer des listes d'objets construit dynamiquement a la volé.

Si vous souhaitez retrouver ce code, tout cela est dans [github]

Références

[manip-data] https://un-est-tout-et-tout-est-un.blogspot.com/2018/09/python-manipulation-des-donnees.html
[iterateur] https://un-est-tout-et-tout-est-un.blogspot.com/2017/11/design-pattern-literator.html
[github] https://github.com/collonville-tom/tc-un-est-tout-et-tout-est-un/tree/master/Python-Liste-Generateur

Aucun commentaire:

Enregistrer un commentaire