Conditions et notion de boucles

Ce contenu est obsolète. Il peut contenir des informations intéressantes mais soyez prudent avec celles-ci.

Effectuer des calculs, manipuler des variables c'est bien, pouvoir prendre des décisions en fonction des résultats, c'est plus marrant.

Les structures conditionnelles

Nous allons commencer par un exemple. Notre but est de demander l'âge de l'utilisateur et de déterminer si il/elle a plus de 16 ans par exemple.

1
2
3
4
age = int(input("Quel est votre âge ? ")) # Souvenez-vous, il faut convertir en un entier

if age > 16: # Si l'âge est strictement supérieur à 16 (ans)
    print("Vous avez plus de 16 ans :)")

Voyons ce qui s’est passé. Nous avons commencé par demander son âge au visiteur tout en nous assurant de récupérer un entier. Nous avons ensuite effectué un test : si la variable age est supérieur à 16, on affiche un message. Dans le cas contraire rien ne se passe. Nous verrons les différents tests que l'on peut effectuer dans la suite de ce chapitre, mais pour l'instant concentrons-nous sur la structure.

Vous avez sans doute remarqué la présence d'espaces devant le print. On appelle indentation le fait de décaler une ou plusieurs lignes de code à l'aide d'espaces, généralement 4 comme recommandé par Python, ou d'une tabulation (touche Tab à gauche de la touche A). Cette indentation est requise pour le bon fonctionnement de la condition. En effet, Python a besoin de savoir ce qui doit être exécuté uniquement si la condition est vérifiée et ce qui sera toujours exécuté. Les lignes indentées après le if forment les instructions qui seront uniquement exécutées si la condition est vérifiée. Les lignes alignées avec le if seront, elles, toujours exécutées.

A partir de maintenant, vous êtes susceptibles de rencontrer une IndentationError. Ce type d'erreur indique que vous avez un problème d'indentation. Il peut s'agir d'un if qui n'est suivi d'aucun bloc indenté ou d'un nombre incohérent d'espace utilisé tout au long de votre programme : si vous utilisez 4 espaces pour indenter la première fois, n'en mettez pas 5 au if suivant, sinon Python va râler. Si vous utilisez Tab, vous avez probablement oublié ou mis une tabulation de trop.

Maintenant, ajoutons quelques éléments :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
age = int(input("Quel est votre âge ? "))

if age > 16: # Si l'âge est strictement supérieur à 16 (ans)
    print("Vous avez plus de 16 ans :)")
elif age < 0: # Si l'âge est strictement inférieur à 0
    print("Tu te moquerais pas de moi ?")
else: # Dans tous les autres cas
    print("Tu es encore un peu jeune")

print("Au revoir")

Détaillons les trois mots clé introduits :

  • if, c’est-à-dire « si », marque le début de la structure conditionnelle. Il est suivi d'une condition. Il n'y a qu'un seul if dans une même structure conditionnelle. C'est également la première condition à être vérifiée.
  • elif, qui correspond à « sinon si », est aussi suivi d'une condition. Il peut y avoir plusieurs elif dans une même structure de condition. La condition ne sera testée que si aucune des conditions précédentes se trouvant dans la même structure n'est vérifiée. De plus, les elif seront testés dans l'ordre dans lequel ils se trouvent dans votre fichier.
  • else correspond à « sinon » ou « dans tous les autres cas ». Il n'est pas suivi d'une condition. Il n'y a forcément qu'un seul else par structure. En effet, son rôle est d'être nécessairement exécuté si aucune des conditions au-dessus de lui n'a été vérifiée.

Les instructions elif et else peuvent ou non faire partie de votre structure.

Détaillons maintenant notre exemple. Une fois l'âge récupéré, plusieurs scénarios sont possibles :

  • si age est strictement plus grand que 16, print("Vous avez plus de 16 ans :)") est exécuté.
  • sinon si age est strictement plus petit que 0, print("Tu ne te moquerais pas de moi ?") est exécuté.
  • dans tous les autres cas, ce qui correspond ici à un âge entre 0 et 16, print("Tu es encore un peu jeune") est exécuté.
  • Dans tous les cas, c'est-à-dire peut importe l'âge, print("Au revoir") est exécuté.

Dès qu'une condition est vérifiée, le bloc d'instructions associé est exécuté et le programme reprend son exécution à la sortie de la condition, c'est-à-dire dans notre exemple à print("Au revoir"). Ainsi, les conditions suivantes ne seront pas testées et directement ignorées.

Vous pouvez, à la suite de la première condition, en ajouter une deuxième. Celle-ci commencera par un if et sera indépendante de la précédente. Comme toujours, n'hésitez pas à faire des tests.

Maintenant que vous connaissez la structure des conditionnelle, nous allons aborder les différentes conditions que vous pouvez utiliser.

Les opérations logiques

Un nouveau type variable

Et devinez quoi, on s'en est servi sans même le voir. Je vous présente donc le type booléen (bool pour les intimes) :

1
2
3
vrai = True # Notez bien la majuscule
faux = False # Ici aussi
print(type(vrai)) # Affiche <class 'bool'>

Et voilà. Mesdames et messieurs merci pour vos applaudissements. :honte: Plus sérieusement, le type bool ne prend que deux valeurs, vrai (True) et faux (False). Vous l'avez peut être compris, il s'agit donc du résultat d'un test. Ainsi, un if est considéré comme vérifié si la condition renvoie True. Un peu de vocabulaire, la condition est appelée le prédicat, et nous emploierons ce terme à présent.

Les comparaisons

La description parle d'elle-même, je passerai donc rapidement sur ce point, mais comme toujours, n'hésitez pas à tester.

Opérateur Description
a > b a strictement supérieur à b
a < b a strictement inférieur à b
a >= b a supérieur ou égal à b
a <= b a inférieur ou égal à b
a != b a différent de b
a == b a égal à b

Attention à ne pas confondre = et ==. Le premier effectue une affectation, le second une comparaison.

Le prédicat, après évaluation, donne une variable de type bool. Ainsi, si a est un booléen, if a: équivaut à if a == True:.

Combinaison

Vous pouvez utiliser plusieurs de ces opérateurs dans une même condition :

1
2
print(7 > 5 > 1) # Affiche True
print(7 > 5 < 9 != 10) # Affiche True

Vous pouvez bien entendu utiliser des variables. Attentions toutefois à ne pas abuser de ce type de conditions, vous pourriez vous retrouver avec des conditions rapidement peu incompréhensibles, surtout si vous devez vous relire après plusieurs mois. On retiendra néanmoins qu'il est facile de tester des encadrements, notamment de variables, en utilisant cette méthode.

Les opérateurs logiques

Il est possible d'imbriquer des conditions en écrivant un if dans un if comme ceci :

1
2
3
if couleur == "rouge":
    if poids > 10:
        # La couleur est rouge et le poids supérieur à 10

Bien qu'utile dans certains cas, dans cet exemple, il serait plus pratique de combiner des prédicats. Ça tombe bien, c'est justement ce dont nous allons parler.

Le ET logique

Supposons que nous avons deux prédicats A et B. Nous allons nous intéresser au ET logique. Le tableau qui suit est appelé table de vérité de ET. Le tableau se lit comme suit : pour une ligne donnée, les deux premières colonnes indiquent la valeur de vérité du prédicat A et B (c'est-à-dire si oui ou non ils sont vérifiés). La troisième colonne donne alors la valeur de vérité de l'opération logique étudiée. Ainsi par exemple, la première ligne de la table suivante signifie : « si le prédicat A n'est pas vérifié et si le prédicat B n'est pas vérifié, alors le prédicat A ET B n'est pas vérifié ». Si vous vous faîtes des recherches sur le net, vous trouverez peut-être des tables de vérités utilisant 1 pour représenter True et 0 pour False.

A B A ET B
False False False
False True False
True False False
True True True

Je vais vous montrer la syntaxe Python en reprenant l'exemple précédent :

1
2
if couleur == "rouge" and poids > 10:
    # La couleur est rouge et le poids supérieur à 10

Vous pouvez combiner plus de deux prédicats en utilisant plusieurs and.

Le OU logique

Voici tout d'abord sa table de vérité :

A B A OU B
False False False
False True True
True False True
True True True

Cette opération est aussi appelée OU inclusif. C'est à dire que si vos deux prédicats sont être vrais, le OU retournera vrai aussi. Il ne s'agit pas du OU exclusif, qui n'autorise qu'un seul des deux prédicats à être vrai à la fois. Le ou exclusif est celui utilisé dans « fromage ou dessert » : vous n'avez pas le droit aux deux petits gourmands.

Et voici sa notation Python :

1
2
if couleur == "verte" or poids == 15:
    # La couleur est verte ou le poids égal à 15 ou les deux en même temps

De la même façon que pour and vous pouvez utiliser plusieurs or dans un prédicat, et même combiner des and et des or. Il faut néanmoins bien noter que le ET sera prioritaire sur le OU, tout comme la multiplication est prioritaire sur l'addition. Vous pouvez utiliser des parenthèses, comme pour les opérations, afin de changer la priorité.

Le NON logique

Si vous souhaitez vérifier le contraire d'un prédicat, vous pouvez utiliser le NON logique, noté not en Python. Ce dernier diffère des deux précédents car il se place devant un prédicat un n'affecte qu'un seul prédicat.

Voici donc sa table de vérité :

A NON A
False True
True False
1
2
if not (couleur == "bleu" and poids > 20):
    # Si la condition est vérifiée, alors on ne peut avoir simultanément couleur == bleu et poids > 20

Un petit exercice

Souvenez-vous, nous avons parlé du OU exclusif. Pour raccourcir les notations, le OU désigne le ou inclusif, et XOR (de l'anglais « exclusive or ») le OU exclusif. Vous avez peut-être remarqué que je ne vous ai pas donné d'opérateur pour cette opération. C'est normal, Python ne définit pas cette opération par défaut. Rassurez-vous, on peut effectuer cette opération avec les trois opérations que je viens de vous présenter. Et bonne nouvelle, vous allez essayer de la faire vous-même. :) Si, si, ça sera un bon exercice très court.

Si vous ne savez pas par où commencer, je vous propose de subdiviser le problème : essayé d'écrire sa table de vérité dans un premier temps, puis de traduire cette table en langage naturel et enfin d'écrire le code associé. Oui, il y a une correction pour chaque étape, mais essayez de chercher avant de vous jeter dessus. :diable:

Seule la dernière ligne diffère de la table du OU :

A B A XOR B
False False False
False True True
True False True
True True False

Pour la traduction en langage naturel, qui est probablement le plus dur, vous devez obtenir quelque chose d'équivalent à :

Il faut que A soit vrai et pas B ou que B soit vrai et pas A pour que le prédicat soit vérifié

Je vais noter A et B deux variables de type bool. Elles peuvent bien sûr être remplacées par un prédicat.

1
(A and not(B)) or (B and not(A))

Vous pouvez effectuer des tests afin de vérifier que nous suivons bien la table de vérité attendue.

Si vous souhaitez en apprendre plus sur les prédicats, vous pouvez regarder du côté de l'Algèbre de Boole.

Première boucle

Pour mieux illustrer l'utilité des boucles, nous allons chercher à calculer le PGCD de deux nombres. Pour rappel, le PGCD de deux nombres est le plus grand entier divisant simultanément ces deux entiers. Par exemple, le PGCD de 15 et 12 est 3 car $15=5\times3$ et $12=4\times3$. Pour le calculer, nous allons utiliser l'algorithme d'Euclide. Celui-ci repose sur le principe suivant :

  • Le PGCD de 0 et d'un entier a est l'entier a
  • Le PGCD de deux entiers a et b est égal au PGCD de b et de a mod b, c'est à dire $\text{PGCD}(a,b) = \text{PGCD}(b,a\> \text{mod}\> b)$

mod représente l'opération modulo de Python, c'est à dire %. Cette méthode fonctionne car a mod b est strictement plus petit que a et reste positif. Ainsi, en répétant la deuxième étape un certain nombre de fois, nous allons pouvoir nous ramener à la première étape et obtenir notre PGCD.

Facile ? Vous pouvez-essayer mais vous allez avoir un petit problème : combien de fois faut-il exécuter la deuxième étape ? Eh bien, autant de fois qu'il le faut. :-° Le nombre d'étapes dépend de a et b, et puis si je vous avais dit 50 étapes, vous auriez fait 50 copier-coller de la deuxième étape ? Nous allons donc utiliser une boucle pour effectuer le travail.

Une boucle while, qui signifie « tant que » en anglais, permet d'exécuter un bloc d'instructions tant qu'un certain prédicat est vérifié. Voyons comment utiliser cette fameuse boucle en Python.

Schéma illustrant la structure d'une boucle

Notre première boucle

Sans surprise, nous allons utiliser le mot-clé while :

1
2
while predicat:
    # Instructions

Tout comme pour le if, les instructions indentées sont à l'intérieur de la boucle, c'est à dire que ce sont les instructions répétées tant que predicat est vrai. predicat peut être remplacé par n'importe quel prédicat vu précédemment.

Si votre prédicat est toujours vrai, alors votre boucle ne s'arrêtera pas et vous aurez alors une boucle infinie. Même s'il est vrai qu'une telle boucle peut être utile, méfiez-vous des boucles infinies indésirables. Python ne se charge pas de déterminer si vous avez programmé ou non ce que vous vous vouliez, il exécute. Donc si vous lui demandez de faire une boucle infinie, il le fera.

Il vous arrivera sûrement de créer de telles boucles par mégarde, mais n'ayez crainte, si cela vous arrive, tapez Ctrl + C dans votre console. Cette combinaison, de manière générale, va interrompre brusquement l'exécution de Python. Vous pouvez alors corriger votre programme et relancer votre code.

Maintenant que je vous ai fait peur que vous êtes averti, essayez de réaliser une boucle de façon à ce qu'à sa sortie, c'est à dire quand elle se termine, a soit égal au PGCD que vous afficherez.

Je vous mets la correction, mais cherchez avant de sauter dessus :p :

1
2
3
4
5
6
7
a = int(input("a:"))
b = int(input("b:"))

while b != 0:
    a, b = b, a%b

print(a)

Tout comme pour un if, vous pouvez mettre ce que vous voulez dans le bloc d'instructions de la boucle.

Deux mots-clés supplémentaires

Nous avons vu que le prédicat d'une boucle doit devenir faux à un moment pour que la boucle s'arrête. Il y a néanmoins une autre façon d'interrompre une boucle avec le mot-clé break. Quand Python rencontre cette instruction, il sort immédiatement de la boucle et continue l'exécution du code située après celle-ci. Par exemple, notre code pour trouver le PGCD peut s'écrire :

1
2
3
4
5
6
7
while True: # Cette boucle ne s'arrêtera pas sauf si ....
    a, b = b, a%b
    if b == 0:
        break # ... on utilise un break pour la stopper
    print(b) # Affiche l'évolution de b

print(a)

Cette méthode rend néanmoins plus difficile la lecture de longues boucles : on voit d'abord une boucle infinie, mais on ne sait pas à quelle condition celle-ci s'arrête. Il faut alors trouver le, ou les break. Remarquez que quand b == 0, l'instruction print(b) ne sera pas exécutée, car située après le break.

Vous serez tenté d'utiliser cette approche si votre prédicat est trop compliqué à exprimer. Néanmoins, si vous souhaitez éviter le comportement du break, qui ne va pas exécuter les instructions suivantes dans la boucle, vous pouvez utiliser une variable. Une telle variable est souvent appelée drapeau ou flag en anglais. Par exemple :

1
2
3
4
5
6
drapeau = True
while drapeau:
    a, b = b, a%b
    if b == 0:
        drapeau = False
    print(b)

Cette fois ci, l'instruction print(b) est exécutée même quand b vaut 0.

Le deuxième mot-clé que je voulais évoquer est continue. Quand Python rencontre cette instruction, il recommence à la boucle à partir du prédicat, sans exécuter la fin du passage en cours. Un exemple pour éclaircir tout ça :

1
2
3
4
5
6
i = 0
while i < 10:
    i += 1 # Pour ne pas avoir une boucle infinie
    if i%2 == 0: # Si i est pair
        continue
    print(i)

Ici, seuls les valeurs impaires de i seront affichées. En effet, si i est pair, continue est exécuté et Python reprend le programme à partir de while i < 10. Notez que l'incrémentation, le fait d'augmenter de façon répétée la valeur de i, est placé au début. Si nous l'avions ajoutée après le continue, nous aurions eu une boucle infinie : l'incrémentation n'aurait plus lieu dès que i est pair, ce qui arrive dès le début avec i = 0.


Maintenant que nous commençons à pouvoir écrire des programmes un peu plus complexes, nous allons regarder comment mieux nous organiser.