Structures conditionnelles

Notion d’instruction composée

Jusqu’à présent on a vu que chaque “ligne” de l’interpréteur acceptait une instruction. L’appui sur la touche entrée entrainait ainsi l’exécution de ladite instruction avant que l’interpréteur nous rende la main.

Les instructions composées se comportent d’une façon différente. Elles sont composées d’une entête et d’un corps principal. Ce dernier est lui même composé de différentes instructions. Il est délimité par le niveau d’indentation c’est à dire l’alignement à gauche.

ATTENTION notez bien que la ligne d’entête se finit toujours par le caractère :

Schématiquement une instruction composée ressemble à:

ENTETE:
    INSTRUCTION1
    INSTRUCTION2
    INSTRUCTION3
    ...
    INSTRUCTION_FINALE
NOUVELLE_INSTRUCTION

Le corps principal commence à INSTRUCTION1 et finit à la ligne INSTRUCTION_FINALE.

ATTENTION le niveau d’alignement n’est pas totalement visuel, car dans de nombreux éditeurs de texte le caractère de tabulation \t semble visuellement comparable à plusieurs espaces. Cependant l’interpréteur python n’accepte pas de tels mélanges. On prendra soin pour éviter des bogues délicats de paramétrer son éditeur de texte pour qu’il insère 4 espaces lors d’un appui sur la touche tabulation.

REMARQUE il faut bien réaliser que rien n’empêche une (ou plusieurs) des instructions d’un bloc d’être elle aussi composée. C’est même fréquent. On arriverait ainsi au schéma

ENTETE1:
    INSTRUCTION1
    ENTETE2:
        INSTRUCTION2
        INSTRUCTION3
    INSTRUCTION4
    ENTETE3:
        ENTETE4:
            INSTRUCTION5
        INSTRUCTION6
    INSTRUCTION7

Le contrôle effectué par l’entête sur le corps de l’instruction composée dépend du type de l’entête utilisée. On va en voir deux exemples maintenant.

Structure if

Version élémentaire

Le bloc conditionnel a une première entête commençant par if (si). Il permet d’exécuter du code lorsqu’une certaine condition est satisfaite.

Sa forme la plus simple est schématiquement

if EXPRESSION_BOOLEENNE:
    INSTRUCTION1
    INSTRUCTION2
    ...
    INSTRUCTION_FINALE
NOUVELLE_INSTRUCTION

Pour des exemples précis.

>>> if True:
...     print("INSTRUCTION1")
...     print("INSTRUCTION2")
...
INSTRUCTION1
INSTRUCTION2
>>> print("NOUVELLE_INSTRUCTION")
NOUVELLE_INSTRUCTION
>>> if False:
...     print("INSTRUCTION1")
...     print("INSTRUCTION2")
...
>>> print("NOUVELLE_INSTRUCTION")
NOUVELLE_INSTRUCTION

ATTENTION l’interpréteur n’exécute qu’une instruction à la fois. Il faut donc laisser une ligne vide pour signaler la fin d’un bloc, la nouvelle instruction sera entrée une fois que l’interpréteur nous aura rendu la main. Dans un script on peut par contre se contenter de revenir en arrière dans l’alignement, même si ce n’est jamais une mauvaise idée d’aérer son code!

Versions complètes

On a une deuxième version de la structure conditionnelle où on fournit un bloc alternatif au cas où l’expression booléenne évalue à False. Ceci est fait au moyen d’une deuxième entête else.

>>> if True:
...     print("Cas True")
... else:
...     print("Cas False")
...
Cas True
>>> if False:
...     print("Cas True")
... else:
...     print("Cas False")
...
Cas False
>>>

Finalement on peut intercaler des expressions booléennes intermédiaires pour examiner plus de cas. Ceci est accomplit via des entêtes elif:

>>> x = 1
>>> if x == 1:
...     print("x vaut 1")
... elif x == 2:
...     print("x vaut 2")
... else:
...     print("x n'est ni 1 ni 2")
...
x vaut 1
>>> x = 2
>>> if x == 1:
...     print("x vaut 1")
... elif x == 2:
...     print("x vaut 2")
... else:
...     print("x n'est ni 1 ni 2")
...
x vaut 2
>>> x = 10
>>> if x == 1:
...     print("x vaut 1")
... elif x == 2:
...     print("x vaut 2")
... else:
...     print("x n'est ni 1 ni 2")
...
x n'est ni 1 ni 2

REMARQUE on peut lire les entêtes de l’instruction composée ci-dessus comme:

ATTENTION les exemples schématiques

if CONDITION1:
    CORPS1
elif CONDITION2:
    CORPS2
else:
    CORPS3

et

if CONDITION1:
    CORPS1
if CONDITION2:
    CORPS2
else:
    CORPS3

sont bien différents.

Structure while

On donne maintenant une deuxième instruction composée commençant par l’entête while (tant que). Elle permet de répéter le corps principal d’instructions tant qu’une condition est satisfaite.

Son schéma est le suivant:

while EXPRESSION_BOOLEENNE:
    INSTRUCTION1
    INSTRUCTION2
    ...
    INSTRUCTION_FINALE
NOUVELLE_INSTRUCTION

ATTENTION il est crucial que dans le corps des variables intervenant dans l’expression booléenne soient modifiées. On risque sinon d’obtenir une boucle qui se répète à l’infini. (On pourra l’interrompre via la combinaison de touche CTRL-C)

>>> x = 0
>>> while x < 10:
...     print(x)
...     x = x + 1
...
0
1
2
3
4
5
6
7
8
9
>>> print(x)
10

ATTENTION il s’avère qu’on peut exceptionnellement remplacer les expressions booléennes par différents objets python. L’interpréteur se chargera de faire une conversion implicite vers un booléen pour décider quoi faire. Les règles de conversions sont parfois subtiles, il convient donc d’être prudent dans l’utilisation. Par exemple:

>>> t = (1, 2, 3)
>>> t
(1, 2, 3)
>>> if t:
...     print("Le tuple n'est pas vide")
...
Le tuple n'est pas vide
>>> t = tuple()
>>> t
()
>>> if t:
...     print("Le tuple n'est pas vide")
...
>>>

et

>>> if "":
...     print("chaine non vide")
...
>>> if "abc":
...     print("chaine non vide")
...
chaine non vide
>>>

les conteneurs seront donc True tant qu’ils ne sont pas vides.

Pour les nombres:

>>> x = 0
>>> if x:
...     print("AHA")
...
>>> x = 1
>>> if x:
...     print("AHA")
...
AHA

il semble que 0 soit False. Le code n’étant pas d’une lisibilité exemplaire on préférerait clairement ici:

>>> if x != 0:
    print("AHA")

Exercices

  1. On suppose qu’on a une variable x: int. (La notation est importante et à retenir, elle signifie qu’on a une variable x pointant vers un objet de type int) Donner une instruction composée affichant x est pair ou x est impair suivant le cas de figure.
  2. On suppose qu’on a nombres: tuple[int] (ici on a une variable nombres pointant vers un tuple d’objets int). Donner un code permettant d’obtenir dans une variable produit: int le produit de tous les éléments de nombres.
  3. On suppose qu’on a une variable n: int. Donner un code qui affiche la suite de nombres obtenu via la règle:

Pour aller plus loin

Pour la structure if

>>> help("CONDITIONAL")

pour les évaluations implicites en booléens:

>>> help("TRUTHVALUE")

et pour la notion de bloc et un paragraphe sur while

>>> help("LOOPING")

Corrections

  1. On utilise l’opérateur % et le test d’égalité

    >>> x = 13
    >>> if x % 2 == 0:
    ...     print("x est pair")
    ... else:
    ...     print("x est impair")
    ...
    x est impair
    >>> x = 12
    >>> if x % 2 == 0:
    ...     print("x est pair")
    ... else:
    ...     print("x est impair")
    ...
    x est pair
  2. On a besoin d’une variable auxiliaire indice qui va nous permettre de parcourir les valeurs du tuple

    >>> nombres = (1, 2, 3, 4)
    >>> indice = 0
    >>> produit = 1
    >>> longueur = len(nombres)
    >>> while indice < longueur:
    ...     produit = produit * nombres[indice]
    ...     indice = indice + 1
    ...
    >>> print(produit)
    24

    On va proposer aussi une version utiliser la déstructuration

    >>> nombres = (1, 2, 3, 4)
    >>> produit = 1
    >>> while nombres:
    ...     premier, *nombres = nombres
    ...     produit = produit * premier
    ...
    >>> produit
    24
    >>> nombres
    []
    ATTENTION en fait aucune des deux versions n’est “la bonne”:

On anticipe un peu sur une leçon à venir (sur l’instruction composée for) pour donner la version “pythonique” (ou pythonesque?)

>>> nombres = (1, 2, 3, 4)
>>> produit = 1
>>> for nombre in nombres:
...     produit = produit * nombre
...
>>> produit
24

REMARQUE notez ici l’utilisation classique d’un pluriel pour le conteneur et du singulier correspondant pour la variable parcourant ce conteneur!

  1. La suite étudiée ici se nomme la suite de Syracuse

    >>> n = 7
    >>> while n != 1:
    ...     if n % 2 == 0:
    ...         n = n // 2
    ...     else:
    ...         n = 3 * n + 1
    ...     print(n, end=", ")
    ...
    22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, >>>