.. _tut-controle: ************************************** Contrôle de l'exécution d'un programme ************************************** Une vidéo de présentation des structures de contrôle... .. raw:: html Comme tout langage de programmation, Python possède les deux structures de contrôle élémentaires permettant l'exécution de programmes complexes : - l'exécution conditionnelle d'un bloc d'instruction ; - la répétition d'instructions. Ces structures de contrôles sont similaires dans leur architecture à celles disponibles dans d'autres langages. Deux choses les distinguent cependant: - la syntaxe : en particulier le parenthésage n'est pas requis pour des expressions simples ; - les blocs d'instructions sont définis par l'indentation et non par une paire d'accolades. Le test conditionnel : :keyword:`if` ==================================== Le test conditionnel s'effectue avec l'instruction classique :keyword:`if` qui évalue une expression logique (booléenne) et exécute les instructions du bloc si elle est vraie. Par exemple:: >>> x = int(input("Entrez un entier: ")) Entrez un entier: 16 >>> if x%2 == 0: ... print(x, " est pair") ... 16 est pair Si la condition est fausse, les instructions du bloc :keyword:`else` sont exécutées:: >>> x = int(input("Entrez un entier: ")) Entrez un entier: 17 >>> if x%2 == 0: ... print(x, " est pair") ... else: ... print(x, "est impair") ... 17 est impair D'autres alternatives sont possibles avec une ou plusieurs instructions :keyword:`elif`. L'utilisation de :keyword:`elif` évite l'imbrication de plusieurs blocs :keyword:`if`. Un test conditionnel est composé de : - 1 instruction :keyword:`if` assortie d'une expression logique (on dit aussi prédicat) ; - 0, 1 ou plusieurs instructions :keyword:`elif`, chacune assortie d'une expression logique ; - 0 ou 1 instructions :keyword:`else`. .. Important:: Python évalue chaque expression logique associée aux instructions :keyword:`if`, :keyword:`elif` dans l'ordre où il les rencontre. Il exécute le bloc correspondant à la première expression logique évaluée à ``True`` puis sort du bloc (les expressions logiques suivantes ne sont pas évaluées). Si toutes les expressions logiques sont évaluées à ``False``, le bloc :keyword:`else` est exécuté (s'il est présent) :: if False: print('if') elif True: print('elif1') elif True: print('elif2') else: print('else') Bien que l'expression logique de la deuxième instruction :keyword:`elif` soit ``True``, le bloc correspondant n'est jamais exécuté. .. admonition:: A expérimenter... Modifier les prédicats ci dessus et observer le comportement du test conditionnel. Python ne possède pas d'instruction ``switch`` comme ce peut être le cas dans d'autres languages. Sa déclinaison en une séquence :keyword:`if` ... :keyword:`elif` ... est fonctionnelle mais lourde. Une implémentation très compacte est possible à partir d'un dictionnaire, comme on le verra dans le paragraphe :ref:`switch`. La répétition d'instructions : :keyword:`for` ============================================= En Python :keyword:`for` permet d'itérer sur tout type de séquence, et exploite l'élément plutôt que l'indice de l'élément, comme c'est généralement le cas dans d'autres langages. C'est très efficace, car dans la très grande majorité des cas, l'indice n'est utile que pour accéder à l'élément. On retrouve ce comportement assez souvent en Python, où des instructions de plus haut niveau sont utilisées par défaut. .. note:: Les informations bas niveau (les indices) sont accessibles si besoin avec la fonction :func:`enumerate`. La boucle :keyword:`for` s'écrit de façon similaire, quel que soit le type de séquence sur laquelle on souhaite itérer:: >>> for i in range(0,5): ... print(i, i**2) ... 0 0 1 1 2 4 3 9 4 16 .. note:: La fonction :func:`range` retourne un itérateur sur une séquence d'entiers. L'indice de départ est inclus, l'indice de fin est exclus. C'est un comportement général en Python. Modification du comportement de la boucle ----------------------------------------- Il existe deux façons de modifier le comportement d'une boucle :keyword:`for`. L'instruction :keyword:`break` .............................. L'instruction :keyword:`break` permet de quitter la boucle prématurément. .. code-block:: python :linenos: :emphasize-lines: 3 for i in range(5): if i == 3: break print(i, i**2) 0 0 1 1 2 4 L'instruction :keyword:`continue` ................................. L'instruction :keyword:`continue` permet de passer à l'itération suivante sans exécuter les instructions du corps de boucle qui suivent. .. code-block:: python :linenos: :emphasize-lines: 3 for i in range(5): if i == 3: continue print(i, i**2) 0 0 1 1 2 4 4 16 La clause :keyword:`else` ------------------------- La boucle :keyword:`for` comporte une clause :keyword:`else` permettant l'exécution d'une instruction (ou d'un bloc d'instructions) lorsque la totalité de la boucle a été parcourue. .. code-block:: python :linenos: :emphasize-lines: 5 for i in range(5): print(i, i**2) if i == 9: # cette condition n'est jamais vérifiée break else: print("La boucle est complètement exécutée") print("suite du programme") 0 0 1 1 2 4 3 9 4 16 La boucle est complètement exécutée suite du programme Au contraire, si la boucle :keyword:`for` n'a pas été complètement parcourue, l'instruction contenue dans la clause :keyword:`else` n'est pas exécutée. .. code-block:: python :linenos: for i in range(5): print(i, i**2) if i == 3: break else: print("La boucle est complètement exécutée") print("suite du programme") 0 0 1 1 2 4 3 9 suite du programme La répétition d'instructions : :keyword:`while` =============================================== L'instruction :keyword:`while` permet également la répétition d'instructions comme on vient de le voir pour l'instruction :keyword:`for`. Les deux instructions permettant des constructions équivalentes, le choix entre les deux sera affaire de concision et de clarté. Ainsi, lorsque l'on aura à parcourir une séquence dont la longueur est connue avant l'exécution de la boucle, il sera plus pertinent d'utiliser une boucle :keyword:`for`. A contrario, lorsque le nombre d'itérations n'est pas connu à l'avance et dépend d'une condition évaluée dynamiquement à l'intérieur de la boucle, l'instruction :keyword:`while` permettra une écriture plus naturelle. Un exemple avec la suite de `Syracuse `_. .. code-block:: python :linenos: s = 9 while s != 1: if s % 2 == 0: s = s // 2 else: s = 3 * s + 1 print(s, end=" ") print() 28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1 .. note:: La conjecture de Syracuse est l'hypothèse mathématique selon laquelle la suite de Syracuse de n'importe quel entier ``n`` strictement positif finit par atteindre 1. En mathématiques, une `conjecture `_ est une assertion pour laquelle on ne connaît pas encore de démonstration, mais que l'on soupçonne d'être vraie, en l'absence de contre-exemple. La boucle :keyword:`while` dispose également des instructions :keyword:`break` et :keyword:`continue` pour modifier son comportement. Dans le code ci dessous, la boucle s'arrête prématurément si le nombre ``17`` est trouvé dans la séquence. .. code-block:: python :linenos: n = 9 while n != 1: if n == 17: break if n % 2 == 0: n = n // 2 else: n = 3 * n + 1 print(n, end=" ") print() 28 14 7 22 11 34 17 Ce qu'il faut retenir ===================== .. quiz:: quizz-03 :title: Contrôle de l'exécution d'un programme - Les 3 instructions :quiz:`{"type":"FB","answer":"if elif else","flags":"sequence"}` peuvent être utilisées dans un test conditionnel - Les 2 instructions :quiz:`{"type":"FB","answer":"for while","flags":"sequence"}` peuvent être utilisées pour la répétition d'instructions - L'instruction :quiz:`{"type":"FB","answer":"else", "size":3}` associée à :keyword:`for` permet d'exécuter un bloc d'instructions si la boucle n'a pas été interrompue - :quiz:`{"type":"TF","answer":"F"}` Un test conditionnel peut contenir plusieurs instructions :keyword:`if` - :quiz:`{"type":"TF","answer":"T"}` Un test conditionnel peut contenir plusieurs instructions :keyword:`elif` - :quiz:`{"type":"TF","answer":"F"}` Un test conditionnel peut contenir plusieurs instructions :keyword:`else` - :quiz:`{"type":"TF","answer":"F"}` Toutes les expressions logiques d'un test conditionnelles sont évaluées - Si on connaît a priori le nombre d'itérations à exécuter, le choix d'une boucle :quiz:`{"type":"FB","answer":"for", "size":3}` est pertinent - Si on ne connaît pas a priori le nombre d'itérations à exécuter, le choix d'une boucle :quiz:`{"type":"FB","answer":"while", "size":3}` est pertinent - :quiz:`{"type":"TF","answer":"T"}` Une répétition d'instruction écrite avec :keyword:`for` peut également être écrite avec :keyword:`while` - :quiz:`{"type":"TF","answer":"T"}` Une répétition d'instruction écrite avec :keyword:`while` peut également être écrite avec :keyword:`for` - :quiz:`{"type":"TF","answer":"F"}` La bonne pratique d'utilisation d'une boucle :keyword:`for` est de manipuler les indices - :quiz:`{"type":"TF","answer":"T"}` L'utilisation de l'instruction :keyword:`break` dans une boucle :keyword:`for` ou :keyword:`while` permet d'interrompre définitivement le parcours de la boucle - :quiz:`{"type":"TF","answer":"T"}` L'utilisation de l'instruction :keyword:`continue` dans une boucle :keyword:`for` ou :keyword:`while` permet d'interrompre momentanément le parcours de la boucle