top of page

BOUCLE FOR ET ITÉRABLES

La boucle for permet de reproduire plusieurs fois une ou plusieurs actions. En Python, les actions ne sont pas délimités par des accolades comme pour le langage C, il faut cependant utiliser une tabulation à chaque ligne de code.

La boucle for la plus connue est celle utilisant la fonction range :

for i in range(n): # i va de 0 à n-1

    actions

for i in range(0,n): # i va de 0 à n-1

    actions

for i in range(0,n,2): # i va de 0 à n-1 avec un pas de 2

    actions

for i in range(10,-10,-1): # i va de 10 à -10 avec un pas négatif

    actions

Ce que vous ne savez peut-être pas ce que i est appelé un itérateur (indice d'une boucle) et que la fonction range renvoie un itérable. Un itérable est un objet sur lequel on peut itérer, c'est-à-dire sur lequel on peut boucler avec une boucle for.

Les listes et les chaînes de caractères sont toutes deux des itérables, tout comme les tuples (listes non modifiables), les sets (listes ordonnées sans doublon), les dictionnaire et les générateurs. C'est pourquoi on peut itérer sur des chaînes ou des listes avec une boucle for.

Itération sur une chaîne de caractères :

chaine = 'azerty'

for caractere in chaine # La variable caractere prendra la valeur de chaque caractère de la chaîne (un caractère par tour de boucle)

    print(caractere)  # Affiche a puis z puis e ... jusqu'à y

Le principe est le même pour l'itération sur une liste :

liste = [1,2,3]

for element in liste # La variable element prendra la valeur de chaque élément de la liste (un entier par tour de boucle)

    print(element)  # Affiche 1 puis 2 puis 3

Cela marche aussi pour les listes de listes :

listes = [[1,2,3], [4,5,6], [7,8,9]]

for element in listes # La variable element prendra la valeur de chaque liste de la variables listes

    print(element)  # Affiche [1,2,3] puis [4,5,6] puis  [7,8,9]

    for sous_liste in element 

        print(sous_liste)  # Affiche chaque élément de la première sous_liste puis ceux de la deuxième et enfin de la troisième

Enfin, pour lire une liste à l'envers, on utilise la fonction reversed.

for element in reversed(liste):

    actions

La fonction reversed inverse l'itérable mais ne renvoie rien. La ligne suivante ne marche donc pas :

liste_inversee = reversed(liste) # liste_inversee = None

Je vous conseille, si vous voulez obtenir la liste inversée, de la créer avec, par exemple, une compréhension de liste.

liste_inversee = [element for element in reversed(liste)]

Une fonction qui peut parfois être utile est la fonction zip qui permet d'avancer en même temps sur plusieurs itérables. À noter que la boucle s'arrêtera quand la lecture du plus petit itérable sera finie.

liste1, liste2 = [1,2,3],[4,5,6,7,8]

for element1, element2 in zip(liste1,liste2):

    print(element1, element2)  # Affiche 1 4 puis 2 5 puis 3 6

La fonction enumerate est très utile quand on boucle sur une liste, elle permet d'avoir à la fois l'élément de la liste et son rang c'est-à-dire l'indice du tour de boucle.

for indice, element in enumerate(liste):

    print(f'À la position {indice} on trouve l'élément {element}') 

Les fonctions break et continue sont intéressantes car elles permettent de changer le cours normal d'une boucle. 

Par exemple, la fonction break permet de sortir de la boucle. Cela peut être utile pour optimiser un programme en diminuant le nombre de tours inutiles.

 

Exemple avec la recherche du premier 1 d'une liste :

for indice, element in enumerate(liste):

    if element == 1:

        print(f'le premier 1 de la liste a été trouvé à l'indice {indice} de la liste !') 

        break # Une fois le premier 1 trouvé, il est inutile de continuer à boucler, on peut sortir de la boucle

La fonction continue permet quant à elle de passer à l'indice suivant, c'est-à-dire au tour de boucle suivant.

for caractere in chaine:

    if caractere not in ['a','b','c']:

        continue # Saute à l'indice suivant, on n'exécutera pas les actions après le continue.

    actions

Une dernière astuce que je peux vous donner est d'utiliser l'underscore (symbole _) si vous n'avez pas besoin d'utiliser d'indice dans votre boucle. Cela est utile pour répéter plusieurs fois la même action sans se soucier du numéro du tour de boucle.

from random import choice

for _ in range(10): # Inutile de nommer l'indice car il n'est pas utiliser dans la boucle

    print(choice(liste)) # Affiche 10 fois un élément tirer au hasard dans la liste

Enfin, j'aimerais clôturer cette fiche avec une présentation des générateurs. En Python, les générateurs ont été créés afin de simplifier la création d'itérateurs utilisées dans les boucles for.

Les générateurs sont à la croisée entre les boucles et les fonctions. Ils se créent avec des fonctions dites "génératrices" créées de la même manière que les fonctions classiques mais utilisent le mot clé yield à la place de return. Bien souvent, yield est inséré dans une boucle for. C'est d'ailleurs grâce à ce mot clé que l'on va pouvoir renvoyer une valeur (un itérateur) à chaque appel du générateur.

La plupart du temps, on utilise un générateur avec un for, de la même manière qu'on utiliserait un itérable.

for elt in generateur:

    actions

Exemple d'un générateur :

def mon_generateur(chaine):

    precedent = None

    for caractere in chaine:

        if caractere == 'a':

            yield precedent # Si le caractère lu est 'a', on retourne le caractère précédent

        precedent = caractere

Utilisation avec une boucle for :

for caractere in mon_generateur('eazioapghajkl'):

    print(caractere) # Affiche 'e' puis 'o' et enfin 'h'

On peut aussi utiliser la fonction next qui renvoie l'élément suivant du générateur. À chaque appel de next, le générateur est "consommé" et renvoie une valeur. Si on utilise autant de fois la fonction next que le générateur a de valeurs à renvoyer, cela aura le même effet que son utilisation dans une boucle for.

gen = mon_generateur('eazioapghajkl')  # Objet de type generator

print(next(gen)) # Affiche 'e'

print(next(gen)) # Affiche 'o'

print(next(gen)) # Affiche 'h'

Si on utilise la fonction next alors que le générateur a été totalement consommé, Python nous renverra le message d'erreur StopIteration. C'est pourquoi il est souvent conseillé d'utiliser les générateurs avec un for plutôt qu'avec next.

print(next(gen)) # StopIteration car les trois yield (renvoyant 'e',  'o' et 'h') on été "consommé" par les trois next précédents.

bottom of page