Informatique générale pour l’ingénieur Chapitre II : Contrôle de flux d’exécution – Sélection et répétitions Au chapitre précédent, nous avons fait un rapide tour du propriétaire. Nous avons vu que l’interpréteur Python manipulait des données de différentes sortes (float , int , string …) et que, pour réaliser la tâche demandée, il effectuait les instructions programmées dans l’ordre où il rencontrait dans le script. I. Généralités Le « chemin » suivi par Python à travers un programme est appelé un flux d’exécution, et les constructions qui le modifient sont appelées des instructions de contrôle de flux. Les structures de contrôle sont les groupes d’instructions qui déterminent l’ordre dans lequel les actions sont effectuées. Il en existe seulement trois : 1) la séquence : les instructions y sont suivies linéairement dans l’ordre où elles se présentent. Cette affirmation peut vous paraître banale et évidente à première vue. L’expérience montre cependant qu’un grand nombre d’erreurs dans les programmes d’ordinateur sont la conséquence d’une mauvaise disposition des instructions. Plus vous progresserez dans l’art de la programmation, plus vous vous rendrez compte qu’il faut être extrêmement attentif à l’ordre dans lequel vous placez vos instructions les unes derrière les autres. Par exemple, comparons le résultat des deux séquences suivantes a, b = 3, 7 a, b = 3, 7 a=b b=a b=a a=b print(a, b) print(a, b) 2) la sélection : C’est la rencontre d’un carrefour, l’interpréteur est amené à faire un test et à suivre tel ou tel chemin en fonction du résultat de ce test. Dans nombre de recettes de cuisine, on trouve ce genre de branchement : « Si le chocolat utilisé est du chocolat noir, rajouter de la crème fraîche » 3) la répétition et qui amène l’interpréteur à revenir sur ces pas pour répéter un bloc d’instruction. Par exemple dans un protocole de titrage acido-basique : « tant que le virage n’est pas observé, rajouter 1ml de solution titrante ». II. Sélection ou exécution conditionnelle Pour écrire des applications véritablement utiles, il nous faut des techniques permettant d’aiguiller le déroulement du programme dans différentes directions, en fonction des circonstances rencontrées. Pour ce faire, il faut disposer d’instructions capables de tester une certaine condition et de modifier le comportement du programme en conséquence. 1) L’instruction conditionnelle de base est l’instruction if (trop dur la traduction anglaise de si !) Observons la syntaxe sur un exemple : x=float(input('Entrez au clavier un nombre x: ')) En resumé : if (x>100): Rappel : on a appris les tests (True et False au chapitre précédent) print('x est un grand nombre') 1 if(test) : 2) Importance de l’indentation x=float(input('Entrez au clavier un nombre x: ')) x=float(input('Entrez au clavier un nombre x: ')) if (x>100): if (x>100): print('x est un grand nombre') print('x est un grand nombre') print('x est positif') print('x est positif') Attention !! Les limites des blocs d’instructions sont définies par l’indentation : elle est obligatoire. 3) Instructions else et elif x=float(input('Entrez au clavier un nombre x: ')) On peut faire mieux encore en utilisant aussi l’instruction elif if (x>=0): x=float(input('Entrez au clavier un nombre x: ')) print('x est positif ou nul') if (x>0): else : print('x est strictement positif') print('x est strictement négatif') elif x<0: # elif est la contraction de else if Comme vous l’aurez certainement déjà compris, l’instruction else (sinon, en anglais) permet de programmer une exécution alternative, dans laquelle le programme doit choisir entre deux possibilités. print('x est strictement négatif') else : print('x est nul') 4) Tests imbriqués : Il est parfaitement possible d’imbriquer les unes dans les autres plusieurs instructions composées, de manière à réaliser des structures de décision complexes. Exemple : x=float(input('Entrez au clavier un nombre x: ')) if (x>0): print('x est strictement positif') if x>100 and x<200: print ('x est de plus compris entre 100 et 200') elif x>=200: print (' x est tres grand !') else: print ("""x n'est pas tres grand""") elif x<0: # elif est la contraction de else if print('x est strictement négatif') else : print('x est nul') Remarque importante Vous devrez faire très attention à ne pas utiliser tantôt des espaces, tantôt des tabulations pour indenter les lignes d’un même bloc. En effet, même si le résultat paraît identique à l’écran, espaces et tabulations sont des codes binaires distincts : Python considérera donc que ces lignes indentées différemment font partie de blocs différents. Il peut en résulter des erreurs difficiles à déboguer. En conséquence, la plupart des programmeurs préfèrent se passer des tabulations. Si vous utilisez un éditeur de texte « intelligent », vous avez tout intérêt à activer son option « Remplacer les tabulations par des espaces » 2 III. Instruction répétitives : première approche L’une des tâches que les machines font le mieux est la répétition sans erreur de tâches identiques. Il existe plusieurs méthodes pour programmer ces tâches répétitives. En programmation, on appelle boucle un système d’instructions qui permet de répéter un certain nombre de fois toute une série d’opérations. Python propose deux instructions particulières pour construire des boucles dont l’instruction while que nous allons découvrir tout de suite A) L’instruction while : boucle conditionnelle 1) Premier exemple a = 0 # (initialisation du compteur) while (a < 4): # (n’oubliez pas le double point !) print(a)# (n’oubliez pas l’indentation !) b= 5*a print (b) a = a + 1 # (incrémentation du compteur) print('a la fin de boucle a vaut :',a,' b vaut :',b) Commentaires et conseils • Le mot while signifie tant que en anglais. Cette instruction indique a Python qu’il lui faut répéter continuellement le bloc d’instructions qui suit, tant que le résultat du test impliquant la valeur du compteur reste True ; • Le compteur intervenant dans la condition doit exister au préalable. Il doit être initialisé à l’extérieur de la boucle. • Si la condition reste toujours vraie, alors le corps de la boucle est répétée indéfiniment (tout au moins tant que Python lui-même continue à fonctionner !! Astuce faire Ctr+C pour arrêter l’interpréteur). Il faut donc veiller a ce que le corps de la boucle contienne au moins une instruction qui change la valeur du compteur intervenant dans la condition évaluée par while, de manière à ce que cette condition puisse devenir fausse et la boucle se terminer. • Toujours vérifier si a)dans tous les cas possibles de le code se termine b) Le code se termine avec la bonne valeur Il peut être intéressant de faire tourner le code à la main …. • Si la condition est fausse au départ, le corps de la boucle n’est jamais exécutée. 2) Autre exemple : Racine d’un carré parfait On appelle un carré parfait un nombre entier qui est le carré d’un nombre entier. Dans le programme qui suit on fournit un entier et on regarde s’il est parfait et dans ce cas on trouve sa racine. Le programme qui est présenté ci après est un exemple de « brut force algorithm », on utilise sans trop réfléchir la puissance répétitive de la machine. La stratégie c’est « enumerate and check » : on passe en revue des valeurs « possibles » et on vérifie si ça marche… Ce n’est pas une stratégie très futée … On verra plus tard dans le cours comment rendre compte de l’efficacité d’un algorithme et on verra que certains sont meilleurs que d’autres…. 3 x=121 ans = 0 if x >= 0: while ans*ans < x: ans = ans + 1 print ('essai n°', ans) if ans*ans != x: print (x, """n'est pas un carré parfait """) else: print ('la racine du nombre',x,'est : ',ans) else: print ('x est un nombre négatif') B. Boucle inconditionnelle ou boucle for 1) Les instructions range et for… in La syntaxe est la suivante : For nomDeVariable in Collection : Bloc d’instruction Souvent on a besoin de générer des collections d’entiers La fonction pour cela est range(i; j[; k]) Construit la liste des entiers de i inclus à j exclu. Si k est précisé, les entiers générés vont de k en k à partir de i. par défaut k=1 2) Premier exemple coll = range (1,20,2) print (type (coll)) for c in coll: print (c,end=" ")# observez l'option end de la fonction print 3) Versions for ou version while d’une boucle Les boucles écrites en while peuvent aussi l’être en for. Pour illustrer cela, prenons l’exemple de la recherche de la liste des diviseurs d’un nombre entier Version while x=100 i=2 while i<x: if x%i==0: print(i,'est diviseur de',x) i=i+1 Version for x=100 for i in range (1,x): if x%i==0: print(i,'est diviseur de',x) Commentaires : avantage du for - pas de problème d’initialisation du compteur - on n’a pas à se soucier de l’incrémentation du compteur. La fonction for incrémente automatiquement le compteur en lui faisant balayer la collection - la collection étant un objet fini, on est sûr que sa fin sera atteinte et donc que la boucle se termine. - On verra que la collection peut être autre chose qu’une liste d’entiers ce qu’il faut c’est que ce soit une collection finie. 4