PythonMasterClass

Itinérables

Parcourir une liste

Comme vous l'avez vu précédemment les liste peuvent être parcourus dans des boucles for en revanche vous n'avez pas encore vu comment cela était possible.

Pour qu'un objet soit parcourable il faut qu'il possède une méthode __iter__() qui sera appeller lors de l'entrée dans une boucle ou la fonction iter().

for i in range(3, 10): # appel de __iter__ implicite print(i) for i in range(3, 10).__iter__(): # appel de __iter__ explicite print(i)

Ces deux codes font donc exactement la même chose. On peut aussi le faire sous cette forme.

iterator = range(3, 10).__iter__() while True: try: print(next(iterator)) # ou iterator.__next__() except StopIteration: break

À ce moment vous vous demander ce qui est next, c'est une methode qui permet d'obtenir le prochain élément de l'iterator et dans le cas où il n'y a plus de valeur à renvoyer alors l'exception StopIteration est levé.

Des générateurs !

Comme vous avez pu le voir dans List et tuple, un tuple est déclaré d'une certaine façons

pas_un_tuple = (n*3.14 for n in range(10)) print(pas_un_tuple) un_tuple = tuple(n*3.14 for n in range(10)) print(un_tuple)

Ce code donnera cela comme sortie console

<generator object <genexpr> at 0x000001C19B4F6120> (0.0, 3.14, 6.28, 9.42, 12.56, 15.700000000000001, 18.84, 21.98, 25.12, 28.26)

Comme vous pouvez le voir la syntaxe (expresion de génération) et réserver au générateurs.

Mais quesqu'un générateur ? Est bien un générateur c'est un objet qui crée un iterable sur des valeurs ou objets. Il permet en outre une écriture plus simple des boucles et évite de créé des listes qui prendront plus de place que la gestion d'une valeurs générer une par une.

grande_liste = list(range(100000000)) # iterable plutot q'une deuxième liste iterable_gande_liste_pair = (n for n in grande_liste if n%2==0)

Généralement les générateurs sont utilisé pour les grandes listes évitant de stocker plusieurs fois une même information ou pour construire des objets (comme les listes par compréhension). range est aussi un générateur, il crée une à une les valeurs et pas directement une liste.

reserved et filter, des fonctions sur des iterables

Eh oui, il n'y rien de mieux que ces deux exemples, reversed permet de parcourir dans le sens inverse un iterable sans recrée une liste et sans avoir besoin d'utiliser des indices, pour ce qui est de filter c'est identique, cette fonction ne crée pas une nouvelle liste filtrée mais filtre au moment de l'itération. Pour voir des exemples l'utilisation de filter vous allez voir dans le cours précédant

mot = "salut" for lettre in reversed(mot): #bonne maière print(lettre, end="") print() for i in range(len(mot)): # mauvaise manière print(mot[-i-1], end="")

Zip pour parcourir plusieurs générateurs

zip() est une fonction prenant en paramètre plusieurs itérables pour les parcourir simultanément, vous l'utilser dans de rares cas mais elle est reste très utile lorsque la nécéssité d'un double parcours s'impose

nombres = [1, 2, 3] nom_nombres = ["un", "deux", "trois"] lettres = ["a", "b", "c", "d"] print("zip(nombres, nom_nombres)") for n, nom in zip(nombres, nom_nombres): print(n, nom) print("zip(nombres, lettres)") for n, lettre in zip(nombres, lettres): print(n, lettre)

Sortie Console :

zip(nombres, nom_nombres) 1 un 2 deux 3 trois zip(nombres, lettres) 1 a 2 b 3 c

Dans le prochains cours nous vérons les fonctions génératrices qui sont en lien très fort avec itérables !