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 !