Tests et boucles





Les tests sont des instructions qui permettent d’exécuter une portion de programme si une ou plusieurs conditions sont réalisées.
Les boucles permettent de répéter un traitement sans avoir à réécrire le code correspondant à chaque fois.
Les commandes exécutées à la suite d’un test ou au sein d’une boucle constituent des blocs d’instructions.
Pour rappel, la délimitation d’un bloc d’instructions en Python, qu’il s’agisse de fonctions, de tests ou de boucles, s’effectue par une indentation, c’est à dire par décalage d’une colonne (ou tabulation) entre l’instruction qui lance le bloc d’instructions et les lignes qui composent ce bloc: les instructions qui composent ce bloc doivent donc être alignées verticalement. Bien entendu, si, à l’intérieur du bloc d’instructions, on trouve d’autres tests ou boucles, il faut prévoir d’autres indentations.
 

Les tests de comparaison

 
Une condition est évaluée. Si cette condition est réalisée, une action est effectuée. On peut aussi prévoir d’effectuer une autre action dans le cas contraire:
if <condition>:
<action>
else: [optionnel]
<autre action>

 

Lorsque les alternatives sont multiples, on les évalue à l’aide de elif (contraction de else if). Les tests elif sont alignés (pas d’indentation) sur if et else
 

 

Les traitements en boucle

 
Selon que le nombre d’itérations est connu à l’avance ou conditionné à l’évaluation d’une expression, on utilisera la boucle for in ou la boucle while.

Boucle for

 
Contrairement à la plupart des langages connus, Python n’utilise pas un compteur pour déterminer à quelle étape se trouve l’exécution et, a posteriori, à quel moment le nombre limite d’itérations est atteint. Python utilise à la place un curseur qui va parcourir les éléments d’un ensemble dénombrable (ou itérable en sabir franglais). Ce curseur peut, soit parcourir une collection existante, soit créer une liste pour la circonstance.
Bien que les ensembles itérables ne sont introduits qu’au chapitre suivant (§ Les collections), il est possible de comprendre ce qui suit en posant que:

  • Un ensemble de données encadré par deux crochets est une liste (type list)
    Par ex.

    [0,1,2,3,4]
  • Un ensemble de données encadré par deux parenthèses est un tuplet (type tuple)
    Par ex.

    (0,1,2,3,4)
  • On peut générer n nombres successifs en utilisant le mot-clé range qui agit un peu comme un créateur de séquence contenant ces n nombres. On verra dans la section § Générateurs que range n’est pas du même type suivant les versions de Python. Retenons à ce stade que, utilisé dans une boucle, range(5) joue le même rôle que [0,1,2,3,4]

 
Pour symboliser ce curseur, on utilise un index arbitraire, qui peut être un libellé (nom, article…) ou un simple indice i, j ou n. Dans l’exemple ci-dessous, c’est l’index m qui joue le rôle de curseur parcourant le tuplet celeb
 

Pour accoler une numérotation à la collection, on utilise la fonction enumerate qui associe, dans un tuplet, chaque élément parcouru avec un rang
 

La boucle forin permet aussi de créer une séquence à partir d’une autre séquence de manière remarquablement concise. Cette méthode dite en compréhension sera vue plus en détail dans le chapitre suivant (§ Les collections).
Dans l’exemple ci-dessous, la liste l2 est créée à partir des carrés des valeurs de l1, tandis que l3 ne retient que les nombres divisibles par 3
 

 

Si l’on devait utiliser un bloc d’instructions « standard » pour créer l3, par exemple, on aurait pu écrire
 

Si, à la place de l2+=[y], on écrivait l2+=y, un message d’erreur se produirait à l’exécution

TypeError: ‘int’ object is not iterable

La source de l’erreur est que y est une variable de type int, et que l’opérateur += ne peut mettre en relation que deux opérandes de même type, pas une liste et un entier. Pour augmenter la liste, il faut, soit utiliser la fonction append, soit l’opérateur += après avoir converti y en objet de type list.

Notons que l’on peut créer des listes de listes en remplaçant [y] par [[y]]
 

 
NB: on vérifiera que, dans le cas où les éléments de l3 sont des listes, un changement n’a pas d’effet sur leur adresse.
La possibilité de créer des listes de listes permet de manipuler des tableaux à plusieurs dimensions. En Python « pur », cette représentation n’est pas très lisible, car on préfèrerait visualiser une matrice par exemple sous forme de lignes et de colonnes, au lieu d’une énumération de listes, séparées par une virgule. Nous verrons que cela est néanmoins réalisable en utilisant le package numpy.
En pratique, la création d’une matrice à partir de deux listes, nécessite d’utiliser deux indices, x et y par exemple. Si l’on choisit que x sera l’indice de ligne et y l’indice de colonne, la définition de la matrice m à partir de deux listes l1 et l2 aura la forme générique suivante
 

 

Boucle sur un nombre fixe d’itérations

 
Quand on connaît le nombre d’itérations à effectuer, on va utiliser range qui va incrémenter une variable autant de fois qu’il y a d’itérations.
Dans les versions 2.7, range transforme un chiffre en séquence de type list. Dans la version 3.4, le chiffre est transformé en objet de type… range. Les chiffres incrémentés successivement par range (qui joue le rôle de générateur, mais cela est une autre histoire) peuvent être affichés en bloc à l’aide de la fonction de conversion list.
 

 
Le premier élément de la liste ainsi formée n’est pas obligatoirement 0: on peut ajouter deux arguments à l’itérateur range, le premier désignant la valeur du 1er élément de la liste, le second désignant l’intervalle entre chaque élément, c’est à dire l’incrément. L’itérateur qui suit crée une liste dont la 1ère valeur est 1 et qui progresse de 3 en 3 jusqu’à 10 (non inclus)
 

 
A titre d’exemple applicatif, si on veut calculer une approximation du nombre d’Euler en utilisant les 10 premiers termes de son développement limité

devexp

 

 
Quand il est nécessaire d’utiliser les indices des éléments d’une séquence pour un calcul en boucle, on peut construire un itérateur avec la fonction len (longueur de la séquence):
 

 
Nous avons vu précédemment que l’on pouvait créer des listes de listes (des matrices en général) en compréhension à partir de deux listes à partir de l’exemple suivant
 

 
Le même résultat pourrait être obtenu à l’aide de deux boucles imbriquées et l’itérateur range: le calcul élément par élément n’est pas très intuitif néanmoins, car il faut intervertir l’ordre des boucles – principale et secondaire – par rapport à ce qui viendrait naturellement à l’esprit
 

 

La boucle while

 
Une action est répétée tant qu’une condition est remplie. Par exemple, pour calculer la valeur de e à 0.00000001 près, on fait un développement limité dont le résultat est enregistré dans la variable y et on s’arrête dès que la différence, en valeur absolue, entre y et e, est inférieure à 0.00000001.
 

 
La boucle while est équivalente à forin en utilisant la longueur de la séquence comme limite

 

 
On peut aussi répéter une action jusqu’à ce qu’une condition soit réalisée, en utilisant while True: par exemple, si on veut limiter l’exécution d’une boucle à une certaine durée (1 seconde dans notre exemple)
 

 
Une boucle peut aussi « sauter » certaines étapes