Différentes utilisations de la boucle bornée for en Python et son instanciation

Boucle Tutoriels

Essayons de dompter le tigre… ou plutôt le serpent en l’occurrence. D’ailleurs en parlant d’occurrence, plongeons dans le monde pantagruélique de la programmation et voyons aujourd’hui la boucle for.

A – Mais qu’est ce qu’une boucle, et a fortiori une boucle for ?

Et non ce n’est pas une formule magique, mais presque !

Mais d’abord l’essentiel serait de savoir ce qu’est une boucle en Python puis ensuite de l’adapter à la boucle for (c’est for en chocolat).

Alors comment dire, quand votre petit frère vous énerve tout particulièrement et que vous ne voulez pas rester trop longtemps dans cette géhenne ni faire trop d’escarmouche, alors vous avez une option, non pas la fuite, mais faire tourner en boucle ce personnage qui hante éblouit vos vies.

En lui promettant quelque chose puis en retirant cette promesse, tout en le répétant à de multiples reprises, vous parvenez par la magie du langage, d’objectiver votre conscience, pour qu’ensuite elle l’atteigne au cœur même de sa subjectivité.

Le mal étant fait, profitez de votre œuvre ! Bravo, vous avec compris le concept de boucle et ici c’est une boucle infinie. Super Mince ! Bon, il manque quelque chose pour que la boucle fonctionne vraiment et soit exécutable, c’est à dire pour que ce chérubin fasse ce que vous voulez (sinon il va rester planté là).

Par exemple quand on a peur de vous entendre dire encore une fois que les personnes âgées n’utilisant pas leurs appareils mobiles à bon escient devraient être emprisonnées à vie sur l’île de la Pêche au Sirop, on va dire : « Avant de nous dire cette frivolité tu es priés d’exercer une rotation dans le sens trigonométrique, de ta langue en faisant 7 tours ».

Ainsi vous connaissez déjà les boucles, et ici en plus c’est une boucle for, trop for ! (elle était facile j’avoue)

Donc, vous voyez le cerveau est surprenant de plasticité, vous savez dorénavant quelque chose que vous ne pensiez pas savoir, alors que vous n’avez rien appris de nouveau.

Mais alors que veut dire le mot for, que nos congénères anglicans apprécient tant ?

Selon toute vraisemblance, la traduction la plus logique serait pour, ou bien sur.

Rentrons maintenant que nous appréhendons ces points importants dans le cœur du sujet, et je peux vous dire qu’on est pas sorti du sable.

Alors, il faut savoir qu’en Python (et nous ne parlerons que du Python même si certains éléments seront présents chez d’autres espèces, sélection naturelle oblige), la boule for est une boucle conditionnelle, c’est-à-dire que comme son nom l’indique, elle est soumise à une condition. C’est pourtant clair non ?

Il faut qu’une condition sine qua none se présente pour que la boucle arrête de boucler et que votre frère vous écoute donc on fera attention à cela pour que tout se passe bien.

Pour qu’elle s’arrête il faut aussi un début. Il peut être indiqué explicitement, ou implicitement avec le sens du code.

A savoir que for ne peut pas marcher tout seul comme un grand, il doit obligatoirement être associé à un parent majeur comme une variable ou certaines fonctions.

B – Les différents usages de la boucle for

1. L’association boucle for et fonction range()

Commençons par le plus classique des points, l’appairage avec la fameuse fonction range() !

Donc vous avez un code tel qu’il suit

for i in range(debut, fin, pas):
    # je fais des choses tralalalala

On retrouve donc la structure clé ; l’instruction for, et ensuite un bazar sans nom avec la fonction range().

Décryptons tout cela en partant de la droite.

Alors range() c’est tout bête, c’est juste une fonction qui va aller de la valeur entière donnée de départ à la valeur d’arrivée en répétant cette tâche un nombre certain de fois. Et les pas seront l’écart entre deux valeurs données.

Et en fait i sera une variable temporaire de la boucle automatiquement créée par Python pour récupérer la valeur de la fonction range car sinon elle se perd.

Ainsi si l’on résume, on va parcourir toutes les valeurs entre 2 entiers avec un pas donné !

Ainsi, résumons :

for i in range(42, 50, 2):
	print(i)

Donnera :

42
44
46
48

Car oui il manquait un détail, on ne prend pas la valeur finale, mais la valeur strictement inférieure comme dernière valeur.

Par conséquent, cette boucle peut s’écrire de différentes manières en fonction du niveau de raffinement voulu :

Mode auto :

for i in range(fin):
	# laziza

Ce mode a par défaut un pas de 1 et un début à 0.

Et ici :

for i in range(debut, fin):
	# laziza

Pareil que tout à l’heure sauf qu’on donne explicitement le début.

Et donc tout cela, c’est bien magique, mais voyons un cas concret pour mieux comprendre l’utilisation.

Imaginons que j’ai une liste de matières préférées, classée par ordre de préférence décroissant ; c’est-à-dire que la matière préférée sera en premier, etc…

J’ai donc une liste comme suit :

matieres_preferees = ["NSI", "Maths Expertes", "Maths", "Physique-Chimie", "Philo", "Ma LV2", "Enseignement Scientifique", "SES"] 

Je vais donc dire au grand jour l’ordre de mes matières :

for id_matiere in range(len(matieres_preferees)):
    print("La matiere", matieres_preferees[id_matiere], "est au rang", id_matiere + 1, "dans mon ordre de préférence")
    #ou bien :  print("La matiere {} est au rang {} dans mon ordre de préférence",.format(matieres_preferees[id_matiere], id_matiere + 1) 

En fait ici la fonction len, très utile, donne la longueur de la liste, on parcourt donc la liste de son id 0 (son premier élément), jusqu’à l’id juste inférieur à la longueur de la liste, soit l’id du dernier élément de la liste.

Pour l’affichage, on rajoute un 1 à l’id de la matière, pour donner le rang, car sinon le premier élément aurait le rang 0, peu parlant en langage franchouillard.

Ce code va donc rendre :

La matiere NSI est au rang 1 dans mon ordre de préférence
La matiere Maths Expertes est au rang 2 dans mon ordre de préférence
La matiere Maths est au rang 3 dans mon ordre de préférence
La matiere Physique-Chimie est au rang 4 dans mon ordre de préférence
La matiere Philo est au rang 5 dans mon ordre de préférence
La matiere Ma LV2 est au rang 6 dans mon ordre de préférence
La matiere Enseignement Scientifique est au rang 7 dans mon ordre de préférence
La matiere SES est au rang 8 dans mon ordre de préférence

Et voila vous savez parcourir des nombres à l’aide de for et de range !

2. Le parcours d’éléments autonome (sans valeur chiffrée)

Maintenant, reprenons l’exemple précédant, et affinons le un peu pour le rendre plus élégant.

On va s’avouer quand même que l’écriture de tout à l’heure pour dire l’ordre de nos matières préférées était un peu lourd, redondant, et inutile. Il faut en effet passer par la valeur chiffrée de l’id de l’élément sur la liste pour ensuite arriver à l’élément en lui même. Or, on a vu en philosophie que le fait de traduire sa pensée subjective vers quelque chose d’objectif, comme le langage ou ici la valeur chiffrée, trahissait notre pensée. Donc ce n’est pas bon car cela ne reflète pas exactement ce qu’on veut faire, il faut donc essayer de rester dans notre idée, sans devoir passer par un élément externe pour y arriver.

Or, c’est magique, Python a parfaitement compris cela et nous propose une solution quasiment optimale pour cela ; on parcourt la liste mais sans dire d’autres éléments en utilisant la structure suivante :

for elem in groupe_d_elem:
  	#tralalilala

L’écriture est très simple, et même enfantine, parce que littéralement on dit « Pour chaque élément dans le groupe d’éléments »

A savoir que la variable plus haut nommée elem sera automatiquement créée et mise à jour par Python pour chaque valeur ; rien à faire 😉 !

Donc revenons à notre exemple, cela va donc faire comme suit :

for matiere in matieres_preferees:
  	print("La matiere est :", matiere)

Ce qui rend donc après exécution :

La matiere est : NSI
La matiere est : Maths Expertes
La matiere est : Maths
La matiere est : Physique-Chimie
La matiere est : Philo
La matiere est : Ma LV2
La matiere est : Enseignement Scientifique
La matiere est : SES

On conviendra que c’est bien pratique a écrire et ce de façon simple mais, problème, on a perdu la numérotation des matières pour savoir l’ordre.

C’est là qu’arrive une fonction encore une fois bien pratique de Python ; enumerate.

3. Enumerate, notre sauveur

On reprend donc exactement ce qu’on a écrit tout à l’heure avec le parcours simple sans le range en rajoutant quelques petits détails :

for rang_matiere, matiere in enumerate(matieres_preferees, start=1):
  	print("La matiere est :", matiere, "au rang de preference :", rang_matiere)

Et là, magie, on retrouve notre rang tant manqué !!

La matiere est : NSI au rang de preference : 1
La matiere est : Maths Expertes au rang de preference : 2
La matiere est : Maths au rang de preference : 3
La matiere est : Physique-Chimie au rang de preference : 4
La matiere est : Philo au rang de preference : 5
La matiere est : Ma LV2 au rang de preference : 6
La matiere est : Enseignement Scientifique au rang de preference : 7
La matiere est : SES au rang de preference : 8

En fait ici Python va créer 2 variables ; la variable matière vu comme tout à l’heure et une variable rang_matière, qu’il incrémente à chaque fois de 1 au fur et à mesure du passage à la matière suivante. On lui indique même un bonne valeur de départ pour être certain qu’il parte du bon nombre comme vu tout à l’heure.

Donc si on résume, pour faire ce que l’on a fait c’est-à-dire afficher le rang et la matière deux options s’offrent à nous ; la méthode « Pattes d’Ours » grossière, brutale et peu élégante avec for et la fonction range, ou bien celle avec enumerate, ou la valeur donnée et l’objet sont tous deux présents dans des variables et donc plus facilement utilisables (pour des vérification par exemple avec des tests conditionnels).

En parlant de tests conditionnels d’ailleurs, on peut sortir de la boucle for au bout d’un certain moment si on veut en utilisant break.

Prenons ici notre même exemple et imaginons qu’on veut juste afficher le top 3 des matières, cela fait donc :

for rang_matiere, matiere in enumerate(matieres_preferees, start=1):
    if rang_matiere > 3:
        break
    else:
        print("La matière", matiere, "est au rang de preference :", rang_matiere)

Cela rend donc après exécution :

La matière NSI est au rang de preference : 1
La matière Maths Expertes est au rang de preference : 2
La matière Maths est au rang de preference : 3

Magique non ?

Bien sur, l’inverse est aussi possible avec continue, c’est-à-dire que même si quelque chose est vérifié, on ne sort pas de la boucle, on continue encore.

Passons maintenant à un autre côté magique de Python, une petite astuce sur les chaînes de caractères ; en effet pour lui, ces dernières sont comme des listes, on peut donc les parcourir de la même manière.

Ainsi la phrase :

phrase = "D'apres une etude de l'INSEE la totalite des gens ayant fait NSI en Premiere et en Terminale vivraient heureux et plus longtemps que les autres"

Donnerait ceci en faisant un petit booster pour n’afficher que les mots :

for id_lettre, lettre in enumerate(phrase):
    if lettre == " ":
        pass
    else:
        print(lettre, end="")
        if id_lettre == len(phrase) - 1 or phrase[id_lettre + 1] == " ":
          print("\n")

Cela donnerait donc :

D'apres

une

etude

de

l'INSEE

la

totalite

des

gens

ayant

fait

NSI

en

Premiere

et

en

Terminale

vivraient

heureux

et

plus

longtemps

que

les

autres

On remarquera ici encore quelques petites astuces sur les boucles for. Il y a tout d’abord le pass, qui permet de sauter une répétition si jamais il se passe quelque chose (ici s’il y a un espace), mais aussi les vérifications d’id de la phrase pour savoir si c’est la fin d’un mot ou non.

4. Un petit plus, l’usage de yield associé à la boucle for

yield en Python est un petit peu particulier. Pour le définir, on pourrait le qualifier comme un return, mais qui s’incrémenterait de 1 tout seul à chaque appel. Comme pour return, il ne peut donc être utilisé que dans une fonction.

Voyons un exemple pour mieux l’appréhender :

def nombre_ex():
    for i in range(40,43):
        print("Nouvelle valeur !")
        yield i

On associe donc à yield, la valeur de i comprise entre 40 et 42.

Si on appelle juste la fonction telle qu’elle dans un terminal Python, on obtient un retour étrange :

>>> nombre_ex()
<generator object nombre_ex at 0x100e2a490>

Etrange, la fonction n’est pas perçue comme une fonction, mais comme un générateur, et elle n’est pas exécutée ! C’est tout simplement parce que yield à la place de return joue la place d’un générateur, vu qu’il s’incrémente d’une valeur.

On peut donc utiliser la boucle for sur ce générateur :

temp_iter = nombre_ex()
for elem in temp_iter:
  print(elem)

Ce qui nous fait donc :

Nouvelle valeur !
40
Nouvelle valeur !
41
Nouvelle valeur !
42

C – L’instanciation d’un itération

1. L’itération d’un objet

Pour les adeptes de la POO (Programmation Orientée Objet), n’oublions pas qu’il existe une méthode, pour pouvoir rajouter à votre classe la possibilité d’être itérative selon votre volonté !

Il s’agit de la méthode __iter__ ; comme indiqué dans son nom, elle permet à votre classe de devenir … itérative !

Mais comment concrètement cela marche ?

Voyons déjà sa structure de base et son explication à l’aide d’un exemple neutre.

class maClasse:
    def __init__(self):
        #J'initie ma classe
    #[...]
    def __iter__(self): #autres arguments si voulu
        #Je retourne mon objet itératif
    def __next__(self):
        if condition is verifie:
      		#Je passe à l'élément suivant dans mon itération en suivant certaines conditions
        else:
            raise StopIteration #on stoppe l'itération si la condition n'est pas vérifiée
        
temp = maClasse("""Tartampion""")
for elem in temp:
    #Réaliser une action

Comme vous le voyez, comme pour les méthodes __init__, ou bien __str__ (qui permet d’utiliser la fonction print()), les méthode __iter__ et __next__ sont implicites. Sachez que l’on reconnait ces méthodes dites implicites mais qui sont bien utiles par la présence de doubles underscores (_) avant et après le terme de la méthode.

Ici __iter__ et __next__ sont au cœur même du concept d’itération pour Python. Et c’est ici qu’il faut comprendre quelque chose d’important dans le fonctionnement de for (que je n’exprime que maintenant supposant que si vous êtes ici, c’est que vous maîtrisez mieux tous les concepts de programmation de base).

En effet, pour fonctionner, la boucle for appelle à chaque fois la fonction iter(), sur l’objet sur lequel on est. En ajoutant une méthode __iter__ à notre objet, on le rend donc « itératif » et on fait donc fonctionner la fonction iter(), et ainsi la boucle for. Mais pour l’instant cette boucle va toujours afficher le même élément, car on n’a pas expliqué comment aller à l’élément suivant ; c’est ce qui se passe avec la méthode __next__, on explique à Python comment dans une boucle il pourra aller à l’élément suivant !

Donc voilà, on a pu créer un comportement itératif pour notre classe !

Mais attention, pour pouvoir le faire, il faut bien comprendre et assimiler le fonctionnement de cette dernière, en connaissant bien les conditions de passage d’un élément à l’autre ; en prenant en quelque sorte du recul sur notre objet, pour essayer de se le représenter virtuellement, au risque d’avoir quelques surprises !

2. Des objets itératifs dans des packages

Bien évidemment, vous vous en doutez, s’il est possible de réaliser l’itération dans ses propres classes, de grands packages de classes en sont dotés, comme par exemple le package os.

Ce package présente, comme son nom l’indique, tout ce qui est en lien avec l’OS (ou système d’exploitation en français). Or dans un ordinateur, il y a quelque chose qu’on peut avoir besoin dans un programme Python, qui est présent en nombre et souvent très mal rangé. Et oui, il s’agit des documents présents dans des « directories » (ou dossiers), que la boucle for permet donc aisément de parcourir, comme suit avec ce petit exemple très simple :

import os

for filename in os.listdir("un_dossier/mon_directory/"):
    print(filename)
    if filename.endswith(".py"):
        print("Ohhh un fichier Python !!")

Comme vous le voyez, on a itéré sur les fichiers de notre directory à l’aide de cette classe (qui fonctionne moyennement sur Linux, attention), et cela est faisable sur toute classe sur laquelle le développeur en a laissé la possibilité.

Conclusion

Et voilà, vous êtes enfin arrivés au terme de ce tuto plutôt didactif, votre calvaire et enfin terminé !

Dans tout les cas j’espère que celui-ci vous aura été aussi utile à vous qu’à moi, me permettant de découvrir des talents cachés de la boucle for que je ne vais cesser d’utiliser.

La programmation et l’algorithmique prennent aujourd’hui une place toujours plus prépondérante dans nos vies, et cela ne va cesser de s’accroître. Maîtriser ces concepts de base autour de la programmation peut vous permettre de mieux appréhender ce nouveau domaine en pleine croissance, et ainsi de vous rendre compte qu’il est beaucoup plus éloigné des geeks solitaires à lunettes que vous pensiez, mais plutôt le fruit de logique, d’expériences, d’idées, et de savoir ; se rapprochant en fait d’une logique algorithmique ; mathématique.

Maintenant la boucle for n’aura (presque) plus de secrets pour vous en Python !