Les structures conditionnelles

    Publicités

Users Who Are Viewing This Thread (Total: 0, Members: 0, Guests: 0)

Superman

V
Ancien staff
Dec 2, 2009
2,489
0
596
Vos premières conditions et blocs d'instructions

Forme minimale en if


Les conditions sont un concept essentiel en programmation (oui oui, je me répète à force, mais il faut avouer que des concepts essentiels, on n'a pas fini d'en voir
clin.png
). Elles vont vous permettre de faire une action précise si, par exemple, une variable est positive, et une autre action si cette variable est négative, et encore une troisième si la variable est nulle. Comme un bon exemple vaut mieux que plusieurs lignes d'explications, voici un exemple clair d'une condition prise sous sa forme la plus simple.

N.B.: Dès à présent dans mes exemples, j'utiliserais des commentaires. Les commentaires sont des messages qui sont ignorés par l'interpréteur et qui permettent de donner des indications sur le code (car, vous vous en rendrez compte, relire ses programmes après plusieurs semaines d'abandon, sans commentaire, ce peut être parfois plus qu'ardu
heureux.png
). En Python, un commentaire débute par un dièse (#) et se termine par un saut de ligne. Tout ce qui est compris entre ce # et ce saut de ligne est ignoré. Tous les commentaires sont donc soit sur toute une ligne (on place le "#" en début de ligne) soit après une instruction (on place le # après la ligne de code pour la commenter plus spécifiquement).

Cela étant posé, revenons à nos conditions :

Code : Python Console1
2
3
4
5
6
7
>>> # premier exemple de condition
>>> a = 5
>>> if a > 0: # si a est supérieur à 0
... print("a est supérieur à 0.")
...
a est supérieur à 0.
>>>




Détaillons ce code, ligne par ligne :


  1. La première ligne est un commentaire décrivant qu'il s'agit du premier test de condition. Elle est ignorée par l'interpréteur et sert juste à vous renseigner sur le code qui va suivre.
  2. Cette ligne, vous devriez la comprendre sans aucune aide. On se contente d'affecter 5 à la variable a.
  3. Ici se trouve notre test conditionnel. Il se compose, dans l'ordre :
    • Du mot clé if qui signifie "si" en anglais
    • De la condition proprement dite a > 0 qu'il est facile de lire. Une liste des opérateurs de comparaison possibles sera présentée plus bas.
    • Du signe deux points (:) qui termine la condition. Ce signe est indispensable : Python affichera une erreur de syntaxe si vous l'omettez.
  4. Ici se trouve l'instruction à exécuter dans le cas où a est supérieur à 0. Après l'appui sur entrée à la ligne précédente, l'interpréteur vous présente la série de trois points qui signifie qu'il attend que vous entriez le bloc d'instructions concerné avant de l'interpréter. Cette instruction (et les autres instructions à exécuter s'il y en a) est indentée, c'est-à-dire décalée sur la droite. Des explications supplémentaires seront données sur les indentations un peu plus bas
  5. L'interpréteur vous ré-affiche trois nouveaux points, si vous voulez entrer une nouvelle instruction dans ce bloc d'instructions. Ce n'est pour l'instant pas le cas. Vous appuyez donc sur entrée sans avoir rien écrit et l'interpréteur vous affiche le message "a est supérieur à 0", ce qui est assez logique, vu que a est effectivement supérieur à 0
    smile.png
    .


Il y a deux notions importantes sur lesquelles je dois à présent revenir, elles sont complémentaires ne vous en faites pas.

La première est celle de bloc d'instructions. On entend par bloc d'instructions une série d'instructions qui s'exécutent dans un certain cas précis (par condition, comme on vient de le voir, par répétition, comme on le verra plus tard...). Ici, notre bloc d'instructions n'est constitué que d'une seule instruction (la ligne 4 faisant appel à print). Mais rien ne vous empêche de mettre plusieurs instructions dans ce bloc.

Code : Python1
2
3
4
5
6
7
a = 5
b = 8
if a > 0:
# on incrémente la valeur de b
b += 1
# on affiche les valeurs des variables
print("a =",a,"et b =",b)




La seconde notion importante est celle d'indentation. On entend par indentation un certain décalage vers la droite obtenu, au choix, par un (ou plusieurs) espaces ou tabulations.

J'avais tendance, jusqu'à peu, à utiliser (et conseiller) les tabulations pour marquer l'indentation. Cependant, si on s'appuie sur la Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris! (les PEPs sont les Python Enhancement Proposals : propositions d'amélioration de Python), il est plus judicieux d'utiliser 4 espaces par niveau d'indentation. Je respecterais donc dorénavant cette convention.

Les indentations sont essentielles pour Python. Il ne s'agit pas, comme dans d'autres langages tels que le C++ ou le Java d'un confort de lecture, mais bien d'un moyen pour l'interpréteur de savoir où se trouve le début et la fin d'un bloc.

Forme complète (if, elif et else)


Les limites de la condition simple en if


La première forme de condition que l'on vient de voir est pratique, mais assez incomplète.

Si l'on considère par exemple une variable a de type entier. On souhaite faire une action si elle est positive, et une autre différente si elle est négative. Il est possible d'obtenir ce résultat avec la forme simple d'une condition :

Code : Python1
2
3
4
5
a = 5
if a > 0: # si a est positif
print("a est positif.")
if a < 0: # a est négatif
print("a est négatif.")




Amusez-vous à changer la valeur de a, et ré-exécutez les conditions, vous obtiendrez des messages différents, sauf si a est égal à 0. En effet, aucune action n'a été prévue si a est égal à 0.

Cette méthode n'est pas optimale. Tout d'abord parce qu'elle nous oblige à faire deux conditions séparées pour tester une même variable. De plus, et même si c'est dur à concevoir par cet exemple, dans le cas où la variable remplirait les deux conditions (ici c'est impossible bien entendu), les deux portions de code s'exécuteraient.

La condition "if" est donc bien pratique, mais insuffisante.

L'instruction else:


Le mot-clé else qui signifie "sinon" en anglais, permet de définir une première forme de complément à notre instruction if.

Code : Python1
2
3
4
5
age = 21
if age >= 18: # si age est supérieur ou égal à 18
print("Vous êtes majeur.")
else: # sinon (age inférieur à 18)
print("Vous êtes mineur.")




Je pense que cet exemple suffit amplement à exposer l'utilisation de else. La seule "subtilité" est de bien se rendre compte que Python exécute soit l'un, soit l'autre, et jamais les deux. Notez que cette instruction doit se trouver au même niveau d'indentation que l'instruction if qu'elle complète. De plus, elle se termine également par deux points puisqu'il s'agit d'une condition, même si elle est sous-entendue.

L'exemple de tout à l'heure pourrait donc se présenter comme suit, avec l'utilisation de else :

Code : Python1
2
3
4
5
a = 5
if a > 0:
print("a est supérieur à 0.")
else:
print("a est inférieur ou égal à 0.")




Mais... le résultat n'est pas tout à fait le même, si ?


Non, en effet. Vous vous rendrez compte que cette fois, le cas où a égale 0 est bien pris en compte. En effet, la condition initiale prévoit d'exécuter le premier bloc d'instructions si a est strictement supérieur à 0. Sinon, on exécute le second bloc d'instructions.

Si l'on veut faire la différence entre les nombres positifs, négatifs ou nuls, il va falloir utiliser une condition intermédiaire.

L'instruction elif:


Le mot clé elif est une contraction de "else if", que l'on peut traduire très littéralement par "sinon si". Dans l'exemple que nous venons juste de voir, l'idéal serait de faire :


  • Si a est strictement supérieur à 0, on dit qu'il est positif
  • Sinon si a est strictement inférieur à 0, on dit qu'il est négatif
  • Sinon (a ne peut qu'être égal à 0), a est nul.


Traduit en langage Python, ça donne :

Code : Python1
2
3
4
5
6
if a > 0: # positif
print("a est positif.")
elif a < 0: # négatif
print("a est négatif.")
else: # nul
print("a est nul.")




De même que le else, le elif est sur le même niveau d'indentation que le if de départ. Il se termine de même par deux points, cependant, entre le elif et les deux points se trouve une nouvelle condition. Linéairement, le schéma d'exécution se traduit comme suit :


  1. On regarde si a est strictement supérieur à 0. Si c'est le cas, on affiche "a est positif" et on s'arrête là
  2. Sinon, on regarde si a est strictement inférieur à 0. Si c'est le cas, on affiche "a est négatif" et on s'arrête
  3. Sinon, on affiche "a est nul".


Attention : quand je dis "on s'arrête", il va de soi que c'est uniquement pour cette condition. Si il y a du code après les trois blocs d'instructions, il sera exécuté dans tous les cas.


Vous pouvez mettre autant de elif que vous voulez après une condition en if. Tout comme le else, cette instruction est facultative, et, quand bien même vous construiriez une instruction en if, elif, vous n'êtes pas du tout obligé de prévoir un else après. En revanche, l'instruction else ne doit être mise qu'une fois au maximum, clôturant le bloc de la condition. Deux instructions else dans une même condition ne sont pas envisageables et n'auraient de toute façon pas grand sens.

Sachez qu'il est heureusement possible d'imbriquer des conditions, et, dans ce cas, l'indentation permet de comprendre clairement le schéma d'exécution du programme. Je vous laisse essayer cette possibilité, je ne vais pas tout faire à votre place, non plus
smile.png
.
De nouveaux opérateurs

Les opérateurs de comparaison


Les conditions doivent nécessairement introduire de nouveaux opérateurs, dits opérateurs de comparaison. Je vais les présenter très brièvement, vous laissant l'initiative de faire des tests, car ils ne sont réellement pas difficiles à comprendre.

OpérateurSignification littérale < Strictement inférieur à > Strictement supérieur à <= Inférieur ou égal à >= Supérieur ou égal à == Egal à != Différent de

Attention : l'égalité de deux valeurs est comparée avec l'opérateur "==" et non "=". Ce dernier est en effet l'opérateur d'affectation et ne doit pas être utilisé dans une condition.


Prédicats et booléens


Avant d'aller plus loin, sachez que vos conditions se trouvant par exemple entre "if" et les deux points sont appelés des prédicats. Vous pouvez tester ces prédicats directement dans l'interpréteur, pour comprendre les explications qui vont suivre.

Code : Python Console1
2
3
4
5
6
7
8
>>> a = 0
>>> a == 5
False
>>> a > -8
True
>>> a != 33.19
True
>>>




L'interpréteur renvoie tantôt True (c'est-à-dire "vrai") ou tantôt False (c'est-à-dire "faux").

True et False sont les deux valeurs possibles d'un type que nous n'avons pas vu jusqu'ici : le type booléen (bool).

N'oubliez pas que True et False sont des valeurs ayant leur première lettre en majuscule. Si vous commencez à écrire true sans un 'T' majuscule, Python ne va pas comprendre.


Les variables de ce type ne peuvent prendre comme valeur que vrai ou faux et peuvent être pratiques, justement, pour stocker des prédicats, de la façon dont nous l'avons vu ou d'une façon plus détournée.

Code : Python Console1
2
3
4
5
>>> age = 21
>>> majeur = False
>>> if age >= 18:
>>> majeur = True
>>>




A la fin de cet exemple, majeur vaut "True", c'est-à-dire "vrai", si age est supérieur ou égal à 18. Sinon, il continue de valoir "False". Les booléens ne vous semblent pas très utiles pour l'instant je pense, mais vous verrez qu'ils rendent de grands services.

Les mots clés "and", "or" et "not"


Il arrive souvent que nos conditions doivent tester plusieurs prédicats. Par exemple, si l'on veut savoir si une variable quelconque, de type entier, se trouve dans un intervalle précis (c'est-à-dire comprise entre deux nombres). Avec nos méthodes actuelles, le plus simple serait de faire comme suit :

Code : Python1
2
3
4
5
6
7
8
9
# on fait un test pour savoir si a est comprise dans l'intervalle allant de 2 à 8 inclus
a = 5
if a >= 2:
if a <= 8:
print("a est dans l'intervalle.")
else:
print("a n'est pas dans l'intervalle.")
else:
print("a n'est pas dans l'intervalle.")




Ça marche, mais c'est assez lourd. D'autant que pour être sûr qu'un message soit affiché à chaque fois, il faut fermer d'un else les deux conditions (la seconde étant imbriquée dans la première). Si vous avez du mal à comprendre cet exemple, prenez le temps de le décortiquer, ligne par ligne, il n'y a rien que de très simple.

Il existe cependant le mot clé and ("et" en anglais) qui ici va nous rendre un fier service. En effet, ce qu'on veut tester, c'est si a est supérieur ou égal à 2 et inférieur ou égal à 8. L'on peut donc réduire ainsi nos conditions imbriquées :

Code : Python1
2
3
4
if a>=2 and a<=8:
print("a est dans l'intervalle.")
else:
print("a n'est pas dans l'intervalle.")




Simple et bien plus compréhensible, avouez-le
clin.png
.

Sur le même mode, il existe le mot clé or qui signifie cette fois "ou". Nous allons prendre le même exemple, sauf que nous allons monter notre condition différemment.

Nous allons chercher à savoir si a n'est pas dans l'intervalle. La variable ne se trouve pas dans l'intervalle si elle est inférieur à 2 ou supérieur à 8. Voici donc le code :

Code : Python1
2
3
4
if a<2 or a>8:
print("a n'est pas dans l'intervalle.")
else:
print("a est dans l'intervalle.")




Enfin, il existe le mot clé not qui "inverse" un prédicat. Le prédicat not a==5 équivaut donc à a!=5.

not rend la syntaxe plus claire. Pour cet exemple, j'ajoute à cette liste un nouveau mot clé is qui teste non pas l'égalité des valeurs de deux variables, mais l'égalité de leur référence. Je ne vais pas rentrer dans le détail de ce mécanisme avant longtemps. Qu'il vous suffise de savoir que pour les entiers, les flottants et les booléens, c'est strictement la même chose. Mais en testant une égalité entre variables dont le type est plus complexe, préférez l'opérateur "==". Mais revenons à cette démonstration :

Code : Python Console1
2
3
4
5
6
>>> majeur = False
>>> if majeur is not True:
... print("Vous n'êtes pas encore majeur.")
...
Vous n'êtes pas encore majeur.
>>>




En parlant un minimum l'anglais, ce prédicat est limpide, et d'une simplicité sans égale
langue.png
.

Vous pouvez tester les prédicats plus complexes de la même façon que les précédents, en les entrant directement, sans le if ni les deux points dans l'interpréteur de commande. Vous pouvez utiliser les parenthèses ouvrantes et fermantes pour encadrer des prédicats et les comparer selon une priorité bien précise (nous verrons ce point plus loin si vous n'en comprenez pas l'utilité).
Votre premier programme !

A quoi on joue ?

L'heure est venue pour le premier TP. S'agissant du tout premier, et parce qu'il y a quelques indications que je dois vous donner pour que vous le réalisiez jusqu'au bout, je vous accompagnerai pas à pas dans sa réalisation.

Sujet


Le but de notre programme va être de déterminer si une année entrée par l'utilisateur est bissextile. Il s'agit d'un sujet très prisé des enseignants en informatique quand il s'agit d'expliquer les conditions. Mille pardons donc à ceux qui ont déjà fait cet exercice dans un autre langage, mais, une fois n'est pas coutume, je trouve que ce petit programme reprend assez de thèmes abordés dans ce chapitre pour être réellement intéressant.

Je vous rappelle les règles qui déterminent si une année est bissextile ou non (vous allez peut-être même apprendre des choses que le commun des mortels ignore
langue.png
).

Une année est dite bissextile si c'est un multiple de 4, sauf si c'est un multiple de 100. Toutefois, elle est considérée comme bissextile si c'est un multiple de 400. Je développe :


  • Si une année n'est pas multiple de 4, on s'arrête là, elle n'est pas bissextile.
  • Si elle l'est, on regarde si elle est multiple de 100.
    • Si c'est le cas, on regarde si elle est multiple de 400.
      • Si c'est le cas, l'année est bissextile.
      • Sinon, elle ne l'est pas.
    • Sinon, elle ne l'est pas.


Solution ou résolution


Voilà. Le problème est posé clairement (sinon relisez attentivement l'énoncé autant de fois que nécessaire), il faut maintenant réfléchir à sa résolution en terme de programmation. C'est une phase de transition assez délicate de prime abord, et je vous conseille de schématiser le problème, de prendre des notes sur les différentes étapes, sans pour l'instant penser au code. C'est une phase purement algorithmique, autrement dit, on réfléchit au programme sans réfléchir au code.

Vous aurez besoin, pour réaliser ce petit programme, de quelques indications qui sont réellement spécifiques à Python. Ne lisez donc ceci qu'après avoir cerné et clairement écrit le problème d'une façon plus algorithmique. Cela étant dit, si vous peinez à trouver une solution, ne vous y attardez pas. Cette phase de réflexion est assez difficile au début, et parfois il suffit d'un peu de pratique et d'explications pour comprendre l'essentiel.

La fonction input()


Tout d'abord, j'ai fais mention d'une année entrée par l'utilisateur. En effet, depuis tout à l'heure, on teste des variables que l'on déclare nous-mêmes avec une valeur précise. La condition est donc assez ridicule.

input() est une fonction qui va, pour nous, caractériser nos premières interractions avec l'utilisateur : le programme réagira différemment en fonction du nombre que l'utilisateur entrera.

input() ne prend aucun paramètre. Elle interrompt le programme et attend que l'utilisateur entre ce qu'il veut puis appuie sur Entrée. A cet instant, la fonction retourne ce que l'utilisateur a entré. Il faut donc piéger cette valeur dans une variable.

Code : Python Console1
2
3
4
5
6
7
>>> # test de la fonction input
>>> print("Entrez une année :")
>>> annee = input()
2009
>>> print(annee)
'2009'
>>>




Il subsiste un problème : le type de la variable annee après l'appel à input() est... une chaîne de caractère
blink.gif
. Vous pouvez vous en rendre compte grâce aux apostrophes qui encadrent la valeur de la variable quand vous l'affichez directement dans l'interpréteur.

C'est bien ennuyeux tout ça, nous qui allons devoir travailler sur un entier, nous allons devoir convertir cette variable. Pour convertir une variable dans un autre type, il faut utiliser le nom du type comme une fonction (ce que c'est, d'ailleurs).

Code : Python Console 1
2
3
4
5
6
7
8
9
10
>>> type(annee)
<type 'str'>
>>> # on veut convertir la variable en un entier, on utilise donc
>>> # la fonction int qui prend en paramètre la variable d'origine
>>> annee = int(annee)
>>> type(annee)
<type 'int'>
>>> print(annee)
2009
>>>




Bon, parfait ! On a donc maintenant l'année sous sa forme entière. Notez que si vous entrez des lettres lors de l'appel à input(), la conversion renverra une erreur.

L'appel à la fonction int() en a peut-être déconcerté certains. On passe en paramètre de cette fonction la variable contenant la chaîne de caractère issue de input(), pour tenter de la convertir. La fonction int() retourne la valeur convertie en entier, et on la récupère donc dans la même variable. On évite ainsi de travailler sur plusieurs variables, sachant que la première n'a plus aucune utilité à présent qu'on l'a convertie.


Test de multiples


Certains pourraient également se demander comment tester si un nombre a est multiple d'un nombre b. Il suffit en fait de tester le reste de la division entière de b par a. Si ce reste est nul, alors a est un multiple de b.

Code : Python Console1
2
3
4
5
>>> 5%2 # 5 n'est pas un multiple de 2
1
>>> 8%2 # 8 est un multiple de 2
0
>>>




A vous de jouer


Je pense vous avoir donné le nécessaire pour réussir. A mon avis, le plus difficile est la phase de réflexion qui précède la composition du programme. Si vous avez du mal à réaliser cette opération, passez à la correction et étudiez-la soigneusement. Sinon, on se retrouve à la partie suivante.

Bonne chance !
heureux.png


Correction


C'est l'heure de comparer nos méthodes, et avant de vous divulguer le code de ma solution, je vous précise qu'elle est loin d'être la seule possible et que vous pouvez très bien avoir trouvé quelque chose de différent, mais qui marche tout aussi bien.

Attention... la voiiiciiiiiii...

Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# programme testant si une année, entrée par l'utilisateur,
# est bissextile ou non

print("Entrez une année :")
annee = input() # on attend que l'utilisateur entre l'année qu'il désire tester
annee = int(annee) # risque d'erreur si l'utilisateur n'a pas rentré un nombre
bissextile = False # on crée un booléen qui va être vrai ou faux
# si l'année est bissextile ou non

if annee%400==0:
bissextile = True
elif annee%100==0:
bissextile = False
elif annee%4==0:
bissextile = True
else:
bissextile = False
if bissextile: # si l'année est bissextile
print("L'année entrée est bissextile.")
else:
print("L'année entrée n'est pas bissextile.")




Je pense que le code est assez clair, reste à expliciter l'enchaînement des conditions. Vous remarquerez qu'on a inversé le problème. On test en effet d'abord si l'année est un multiple de 400, ensuite si c'est un multiple de 100, et ensuite si c'est un multiple de 4. En effet, le "elif" garantit que, si annee est un multiple de 100, ce n'est pas un multiple de 400 (car le cas a été traité au-dessus). De cette façon, on s'assure que tous les cas sont prévus. Vous pouvez faire des essais avec plusieurs années et vous rendre compte si le programme a raison ou pas.

N.B.: l'utilisation de bissextile comme d'un prédicat à part entière vous a peut-être déconcerté. C'est en fait tout à fait possible et logique, puisque bissextile est un booléen. Il est de ce fait vrai ou faux et donc on peut le tester simplement. On peut bien entendu aussi écrire if bissextile==True: , cela revient au même.

Un peu d'optimisation


Ce qu'on a fait était bien, mais on peut l'améliorer. D'ailleurs, vous vous rendrez compte que c'est presque toujours le cas. Ici, il s'agit bien entendu de notre condition que je vais passer au crible afin d'en construire si possible une plus courte et plus logique. On peut parler d'optimisation dans ce cas, même si l'optimisation intègre aussi et surtout les ressources consommées par votre application, en vue de les diminuer et d'améliorer sa rapidité. Mais pour une petite application comme cela, je ne pense pas qu'on perdra du temps sur l'optimisation du temps d'exécution
langue.png
.

Le premier détail que vous auriez pu remarquer, c'est que le "else" de fin est inutile. En effet, la variable bissextile est à False par défaut et le reste donc si le cas n'est pas traité (ici, quand l'année n'est ni un multiple de 400, ni un multiple de 100, ni un multiple de 4).

Ensuite, il apparaît que nous pouvons faire un grand ménage dans notre condition, car, les deux seuls cas dans lesquels l'année est bissextile sont "si l'année est un multiple de 400" ou "si l'année est un multiple de 4 mais pas de 100".

Le prédicat correspondant est un peu délicat, il fait appel aux priorités des parenthèses. Je n'attendais pas que vous le trouviez tout seul, mais que vous le compreniez bien à présent.

Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
# programme testant si une année, entrée par l'utilisateur,
# est bissextile ou non

print("Entrez une année :")
annee = input() # on attend que l'utilisateur entre l'année qu'il désire tester
annee = int(annee) # risque d'erreur si l'utilisateur n'a pas rentré un nombre
# si l'année est bissextile ou non

if annee%400==0 or (annee%4==0 and annee%100!=0):
print("L'année entrée est bissextile.")
else:
print("L'année entrée n'est pas bissextile.")




Du coup, on n'a plus besoin de la variable bissextile, c'est déjà ça de gagné. Nous sommes passés de 16 lignes de code à seulement 7 (sans compter les commentaires et les sauts de ligne) ce qui n'est pas rien
clin.png
.

Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!