73
Algorithmique Programmation Département Mesures Physiques — Cours S'1 Laurent POINTAL CNRS/LIMSI [email protected] [email protected] Version 1 — Janvier 2019 24/01/19 15:39

Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

  • Upload
    others

  • View
    13

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

Algorithmique

Programmation

Département Mesures Physiques — Cours S'1

Laurent POINTALCNRS/LIMSI

[email protected]@u-psud.fr

Version 1 — Janvier 2019 24/01/19 15:39

Page 2: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

page 2/73 Algorithmique-Programmation

SommaireI -Introduction................................................................3

I.1 -Styles utilisés......................................................4I.2 -Vocabulaire…......................................................4I.3 -Ordinateur et exécution...................................5

I.3.a -Représentation binaire............................................5I.3.b -Exécution d’un programme....................................6

I.4 -Langage Python.................................................7I.4.a -Mots clés du langage................................................7I.4.b -Structure d’un programme.....................................7I.4.c -Installation de Python..............................................7I.4.d -Tester Python en mode interactif.........................8I.4.e -Tester Python en ligne.............................................8I.4.f -Exécuter des programmes Python.........................9

I.5 -Algorithmique....................................................9I.5.a -Organigramme........................................................10

I.6 -Tester un programme.....................................11I.6.a -Techniques de débogage.......................................11I.6.b -Erreurs en Python..................................................11

II -Types de base...........................................................13II.1 -Nombres...........................................................13

II.1.a -Entiers......................................................................13II.1.b -Flotants (réels)......................................................13II.1.c -Opérations sur les nombres................................14

II.2 -Valeurs logiques.............................................16II.2.a -Opérations booléennes........................................16

II.3 -Textes................................................................17II.3.a -Opérations sur les chaînes..................................19II.3.b -Indexation et sous-chaînes.................................20II.3.c -Méthodes sur les chaînes.....................................20II.3.d -Modifcation d’une chaîne..................................22

III -Variables et afectation........................................23III.1 -Instruction d’afectation.............................23

III.1.a -Utilisation des variables.....................................23III.1.b -Constantes.............................................................24III.1.c -Afectations multiples.........................................24

III.2 -Noms des identifcateurs............................24III.2.a -Règles générales...................................................24III.2.b -Conventions pour l’apprentissage...................25

IV -Afchage et saisie.................................................27IV.1 -Fonction d’afchage.....................................27

IV.1.a -Formatage des valeurs........................................27IV.2 -Fonction de saisie.........................................28

V -Structures de contrôle...........................................29V.1 -Signalisation d’erreur....................................29V.2 -Bloc d’instructions.........................................29V.3 -Instruction conditionnelle si.......................30

V.3.a -Alternative sinon...................................................31V.3.b -Alternatives multiples..........................................32V.3.c -Imbrication de conditions....................................33V.3.d -Choix multiple.......................................................33

V.4 -Instruction de répétition tant que.............33V.4.a -Raccourci de boucle : continuer.........................35V.4.b -Rupture de boucle : stopper................................36

VI -Fonctions.................................................................37

VI.1 -Vocabulaire....................................................37VI.2 -Défnition.......................................................37VI.3 -Utilisation (appel).........................................39

VI.3.a -Arguments d’appel..............................................40VI.3.b -Appels entre fonctions.......................................41

VI.4 -Variables, portée et durée de vie..............43VI.5 -Valeurs de retour..........................................44

VI.5.a -Valeurs multiples.................................................44VI.5.b -Aucune valeur : Procédures..............................45

VI.6 -Efets de bord................................................45VI.6.a -Fonctions pures....................................................45

VII -Tableaux de données..........................................47VII.1 -Déclaration de tableau..............................47VII.2 -Opérations sur les tableaux.....................48

VII.2.a -Indexation............................................................48VII.2.b -Méthodes sur les tableaux................................48VII.2.c -Duplication de tableau......................................49

VII.3 -Instruction de boucle sur tableau...........50VII.3.a -Boucle sur les valeurs........................................50VII.3.b -Boucle sur les indices........................................52

VII.4 -Fonctions et tableaux.................................53VII.4.a -Efet de bord sur paramètre.............................54

VII.5 -Tableaux à 2 dimensions...........................55VIII -Fichiers.................................................................57

VIII.1 -Ouverture/Fermeture...............................57VIII.1.a -Ouverture...........................................................57VIII.1.b -Fermeture...........................................................58

VIII.2 -Lecture.........................................................58VIII.2.a -Lecture de nombres..........................................59

VIII.3 -Écriture........................................................60VIII.3.a -Écriture de nombres.........................................60

IX -Modules...................................................................62IX.1 -Import.............................................................62

IX.1.a -Emplacement........................................................63IX.2 -Défnition.......................................................63IX.3 -Utilisation.......................................................64

X -Programmation Objet...........................................66X.1 -Vocabulaire......................................................66X.2 -Exemple complet...........................................66

X.2.a -Défnition de la classe..........................................66X.2.b -Utilisation de la classe.........................................68

X.3 -Défnition de classe.......................................69X.3.a -Défnition des atributs........................................69X.3.b -Représentation pour l’afchage.........................69

X.4 -Manipulation d’objets...................................69X.4.a -Création...................................................................69X.4.b -Atributs..................................................................69X.4.c -Méthodes.................................................................70

X.5 -Sous-classes.....................................................70X.5.a -Héritage...................................................................70X.5.b -Redéfnition............................................................71

XI -Python pratique....................................................72

Page 3: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

I - Introduction page 3/73 Algorithmique-Programmation

I - Introduction

Le cours, le poly, les TDs et TPs du semestre S'1 ont été revus par rapport au semestre S1 afn de res-treindre certains aspects de programmation spécifques à Python — bien pratiques mais qui peuvent perturber la compréhension — pour pouvoir se concentrer sur les grands principes d’algorithmique et leur mise en œuvre simplement dans des programmes. Ces aspects ignorés sont listés dans le chapitre fnal « Python pratique ».

Pour apprendre à programmer, rien ne remplace la pratique sur ordinateur, avec des problèmes simples au début puis de plus en plus élaborés. Essayez chez vous ou dans les salles informatique à l’IUT, posez des questions à vos enseignants cours/TD/TP.

Pour commencer, un diagramme résumant les éléments abordés dans cete matière :

On retrouve 4 éléments principaux dans ce graphique :

1. on va traiter des données, elles sont au centre de tout,2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème,3. le programme doit permetre d’exprimer l’algorithme et de manipuler des données au cours de

son exécution,4. les instructions du programme s’exécutent en séquence, une par une, sur un ordinateur et

manipulent les données en mémoire.

Page 4: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

I - Introduction page 4/73 Algorithmique-Programmation

I.1 - Styles utilisésDans ce cours nous utilisons les styles de caractères suivants pour les éléments importants et les éléments très importants.Nous utiliserons les styles de paragraphes suivants pour le code :Algorithmique

Programme script Python

Exécution d'un script Python, les saisies de l'utilisateur sont indiquées en gras

Session interactive shell Python, saisies utilisateur en gras

Les exemples de programmes sont colorisés ainsi (commentaire, mot clé, identificateur, littéral) :

# Un exempleimport sysdef affiche_args(lArgs): print("Arguments:") for sa in lArgs: print(sa)affiche_args(sys.argv)

I.2 - Vocabulaire…Le terme français Informatique1 vient d’Information Automatique — c’est la science et la technologie du traitement automatique de l’information. Les anglophones utilisent le terme Computer Science (science des calculateurs).

Le terme français Ordinateur2 a remplacé celui de calculateur, on y retrouve sémantiquement l’ordon-nancement des instructions et le fait de donner des ordres à la machine.

Algorithme3 : Processus systématiques de résolution d’un problème permetant de décrire précisément des étapes pour le résoudre ; le problème consistant en des données en entrée devant aboutir à des données en sortie, la résolution devant être non ambiguë et se faire en un temps fni.

• Systématique → on doit pouvoir l’appliquer à des jeux de données diférentes,

• Précisément → on doit être précis, l’interprétation sémantique doit être claire,

• Étapes → notion de temps, séquencement des opérations à réaliser l’une après l’autre.

Et si on réféchit à la programmation de l’algorithme pour son exécution sur un ordinateur, on peut se poser plusieurs questions :

• Processus → comment exprimer l’algorithme pour que l’humain puisse le rédiger et que l’ordi-nateur le comprenne pour l’exécuter ?

• Systématique → comment être générique dans l’expression pour s’adapter aux jeux de don-nées ?

• Étapes → comment indiquer l’ordre de séquencement ?

• Données → comment les représenter dans le codage binaire de l’ordinateur ?

1 Inventé par Philippe Dreyfus en 1962.2 Inventé par Jacques Perret en 1955, à partir de la description des machines vendues par IBM.3 Algorithme vient du nom du mathématicien, géographe, astrologue et astronome perse Al-Khwârizmî (~780-~850)

Page 5: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

I - Introduction page 5/73 Algorithmique-Programmation

I.3 - Ordinateur et exécutionOn retrouve diférents composants électroniques dans l’ordinateur, que l’on peut schématiser par :

L’ensemble est cadencé par une horloge et fonctionne avec des signaux électroniques sur deux états, représentant des informations numériques sous forme binaire.

I.3.a - Représentation binaireCete représentation utilise des unités d’information appelées « bit », éléments binaires pouvant prendre deux états logiques : 0/1, Faux/Vrai, absence de signal/présence de signal… Tout ce que mani-pule l’ordinateur, programmes et données, est représenté sous cete forme.

Pour noter les valeurs on préfère généralement une notation hexadécimale (base 16) à la notation binaire bien trop longue. À chaque regroupement de 4 bits correspond un chifre hexadécimal :

Binaire Hexa Décimal Binaire Hexa Décimal Binaire Hexa Décimal Binaire Hexa Décimal

0000 0 0 0100 4 4 1000 8 8 1100 C 12

0001 1 1 0101 5 5 1001 9 9 1101 D 13

0010 2 2 0110 6 6 1010 A 10 1110 E 14

0011 3 3 0111 7 7 1011 B 11 1111 F 15

Note : on trouve très souvent le préfxe 0x avant les nombres hexadécimaux (ex. 0x5F78E2).

Pour coller à l’organisation des bits dans l’ordinateur, et pour des facilitées de lecture, on regroupe généralement les bits par paquets de 8 appelés octets (bytes). Chaque octet peut être noté à l’aide de deux chifres hexadécimaux :

01000010 01101111 01101110 01101010 1101111 01110101 1110010 0100001 42 6F 6E 6A 6F 75 72 21

Cet exemple de 8 octets correspond au codage du texte ASCII « Bonjour! ». Il correspond aussi au codage de deux nombres entiers 14022442842 et 11723572729. Il correspond aussi au codage d’un nombre réel 12079297126422283,56655. Il correspond aussi au codage de deux couleurs RGBA4 et . Il corres-pond aussi à une adresse en mémoire sur 64 bits. Ça pourrait aussi être une partie d’une image ou d’un son, ou encore d’un programme sur votre ordinateur.

Suivant le type des données numériques binaires stockées, les octets peuvent représenter difé-rentes informations, on ne les interprétera pas de la même façon et on ne pourra pas faire les mêmes opérations. La défnition précise des types de données manipulées est un élément essentiel lors du passage de l’algorithme au programme, elle détermine les contraintes imposées par la machine et les opérations que l’on pourra efectuer sur les données.

4 RGBA pour Red Green Blue Alpha, valeurs de trois composantes de couleurs ainsi que la transparence, sur un octet chacun.

Page 6: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

I - Introduction page 6/73 Algorithmique-Programmation

Bases de numérationUn rappel concernant les bases dans l’écriture de nombres entiers. Pour un nombre Nβ, exprimé dans la base β, à chaque chifre de N correspond un multiplicateur par une puissance de β utilisée, de gauche à droite en ordre décroissant jusqu’à β0.

Exemples :

1782910 = 1×103 + 7×102 + 8×101 + 9×100 = 1×1000 + 7×100 + 8×10 + 9×1

112012 = 1×23 + 1×22 + 0×21 + 1×20 = 1×8 + 1×4 + 0×2 + 1×1 = 1310

225F16 = 2×163 + 2×162 + 5×161 + 15×160 = 2×4096 + 2×256 + 5×16 + 15×1 = 8799

I.3.b - Exécution d’un programmeSeul langage que comprend le microprocesseur au cœur de l’ordinateur : son langage machine spéci-fque (aussi appelé code machine, code natif ou encore code binaire). C’est un codage purement numé-rique représentant des opérations très basiques et/ou des données.

Il peut être exprimé dans un langage symbolique textuel d’un peu plus haut niveau, appelé langage d’assemblage, à partir duquel un programme assembleur permet d’interpréter les symboles pour générer le programme exécutable en code machine.

Exemple5 de programme assembleur sous Windows (sans les commentaires) :

ORG 100hMOV AH, 09hMOV DX, messageINT 21hRETmessage db "Bonjour le monde !", '$'

Pas très adapté à l’être humain, on a besoin de données de plus haut niveau, d’exprimer des concepts plus abstraits, de comprendre facilement un code écrit… de là sont nés de (très6) nombreux langages de programmation (Lisp, Fortran, Cobol, Algol, APL, Basic, PL/1, Simula, C, Smaltalk, Prolog, Pascal, Forth, SQL, Ada, C++, Eifel, Perl, Haskell, Python, Ruby, Lua, Javascript, Java, PHP, C#, Rust, Go…). La plupart expriment les programmes avec du texte, mais on peut trouver certains langages graphiques (LabView, Pd, NodeBox…).

Chaque langage a ses avantages et inconvénients, est plus ou moins adapté suivant le type de problème que l’on veut résoudre. Ils permetent d’exprimer les algorithmes en ofrant diférents paradigmes7 de programmation (logiques de fonctionnement) parmi lesquels on citera :

• La programmation impérative, où l’exécution d’une séquence d’instructions va modifer l’état des données (la plupart des langages sont impératifs).

• La programmation objet à base de classes, qui est une façon d’organiser et de regrouper les données et les traitements qui y sont liés.

• La programmation fonctionnelle déclarative, qui se rapproche des théories mathématiques.

On distingue historiquement deux modes d’exécution : « compilation » et « interprétation » :

• La compilation : un programme intermédiaire, le compilateur, lit le texte du programme en lan-gage de haut niveau et le traduit en code machine directement exécutable par le processeur. Ensuite, le code machine est directement exécuté par le processeur dans le cadre d’un pro-cessus du système d’exploitation.

• L’interprétation : un programme intermédiaire, l’interpréteur, lit le texte du programme de haut niveau et en assure lui-même l’interprétation ligne par ligne.

5 Source : https://fr.wikiversity.org/wiki/Assembleur/Le_langage_assembleur6 Voir une historique sur https://www.levenez.com/lang/7 Voir https://fr.wikipedia.org/wiki/Paradigme_(programmation)

Page 7: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

I - Introduction page 7/73 Algorithmique-Programmation

Les techniques actuelles mixent allègrement ces deux modes d’exécution, utilisant parfois des représen-tations intermédiaires, appelées byte-code, ou générant directement le code machine par de la compi-lation à la volée juste avant de l’exécuter.

I.4 - Langage PythonLangage créé en 1991 aux Pays-Bas par Guido van Rossum, son utilisation s’est régulièrement étendue dans des domaines très variés ; il est maintenant un des premiers langages pour l’apprentissage de l’al-gorithmique et de la programmation. Il a été introduit dans le cadre de ce cours en 2006 par B. Cordeau. Il permet de metre en œuvre les trois paradigmes de programmation présentés.

Python exécute ses programmes avec une compilation du texte « source » vers une représentation en byte-code intermédiaire, qui est ensuite interprété par un interpréteur « machine virtuelle ». Sa syntaxe très lisible lui permet de passer simplement de l’algorithme au programme et donc de pouvoir rapide-ment tester l’exécution du programme sur des jeux de données.

I.4.a - Mots clés du langageDans les programmes Python, ces mots clés (keywords) sont interprétés avec une signifcation particu-lière : and, as, assert, break, class, continue, def, del, elif, else, except, False, finally, for, from, global, if, import, in, is, lambda, None, nonlocal, not, or, pass, raise, return, True, try, while, with, yield.

Dans ce cours nous n’aborderons pas tous les mots clés.

I.4.b - Structure d’un programmeLes programmes Python sont simplement des fchiers textes, appelés aussi fchiers scripts Python, avec une extension .py. Ils sont formés de lignes qui contiennent les instructions à exécuter, une par ligne8. Le caractère # permet d’introduire des com-mentaires dans le code du programme (du # à la fn de la ligne).

Si l’instruction sur une ligne contient une expression non terminée — un ( ou [ ou { non fermé — alors elle se continue sur les lignes suivantes tant que l’expression n’est pas terminée par le ) ou ] ou } fermant. Un caractère \ tout en fn de ligne permet aussi de poursuivre l’instruction commencée sur la ligne suivante.

L’exécution est réalisée ligne par ligne en parcourant le programme de haut en bas, avec des ruptures et des reprises possibles grâce aux structures de contrôle (cf. p29) et aux fonctions (cf. p33).

Il utilise l’indentation (décalage du texte) pour délimiter les blocs d’instructions9 liées à ces structures de contrôles et fonctions. La structure visuelle du programme est donc l’image de sa structure fonctionnelle. Atention : utiliser des espaces pour réaliser l’indentation, pas le caractère de tabulation (confgurez votre éditeur pour que touche tabulation génère ces espaces).

Un fchier script Python constitue un module (cf. p62), que l’on peut importer pour le réutiliser dans un autre programme.

I.4.c - Installation de PythonPour ne pas perdre inutilement de place dans ce document (nombreuses copies d’écran, cas particuliers suivant les machines, nécessité de mise à jour suivant les problèmes rencontrés…), l’installation de Python est décrite ici : https://perso.limsi.fr/pointal/python:installation:

8 La possibilité de placer plusieurs instructions sur la même ligne — séparées par des ; — est très peu utilisée et est déconseillée.9 Pour délimiter les blocs d’instructions les autres langages utilisent généralement des symboles, comme {}, ou encore des mots clés

comme begin et end.

Page 8: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

I - Introduction page 8/73 Algorithmique-Programmation

Si vous avez déjà un Python de version supérieure ou égale à Python 3.6 avec la librairie matplotlib installée, c’est bon. Sinon, il vous faut faire une réinstallation (ou une installation en plus — plusieurs versions de Python peuvent être installées en parallèle… il faut juste choisir la bonne lorsqu’on exécute un script), dans ce cas voir la documentation d’installation disponible en ligne.

I.4.d - Tester Python en mode interactifPython ofre un mode « calculatrice », permetant de tester facilement de petites expressions (dès que le test devient conséquent il vaut mieux le placer dans un fchier script).

Le plus simple est d’ouvrir l'IDE (Integrated Development Environment) que vous avez choisi et d’utiliser l’interpréteur Python démarre automatiquement dans cet environnement (souvent appelé « Shell Python »). Il afche une invite (ou prompt) sous la forme de >>>10, après laquelle vous pouvez directe-ment saisir des expressions de calcul ou des instructions qui sont exécutées dès que vous validez par la touche Entrée (il peut être nécessaire de la presser deux fois). En mode interactif la valeur résultant d’une expression de calcul est directement afchée.

Qelques exemples :

>>> 20 * 5.5 + 3 * 5 # expression de calcul sur des nombres125.0>>> sLang = "Python 3" # instruction d'affectation>>> (sLang + " ") * 5 # expression de calcul sur du texte'Python 3 Python 3 Python 3 Python 3 Python 3 '>>> for c in sLang: # instruction de boucle suivie d'un bloc d'instructions... print(f"{c} {ord(c)}")... print("---")... P 80---y 121---t 116---h 104---o 111---n 110--- 32---3 51--->>> ((12 + 8) * 4 + # expression de calcul sur des nombres, sur plusieurs lignes... 10 * 2)100

Notez que l’invite est changée en ... lorsque l’interpréteur est en atente de la suite de l’expression ou de l’instruction.

I.4.e - Tester Python en ligneLe site web Python Tutor permet de saisir un programme puis de le tester en visualisant l’état des variables au fur et à mesure de l’exécution. Cela aide beaucoup à la compréhension des modifcations des variables en mémoire au fur et à mesure de l’avancement de l’exécution du programme et des appels de fonctions (sous-programmes).

→ http://www.pythontutor.com/→ http://www.pythontutor.com/visualize.html#mode=editN’oubliez pas de sélectionner Python en version 3.6 ou plus récent.

Lors de la visualisation de l’exécution il est possible avec le bouton Forward d’exécuter les lignes une à une et de suivre dans partie droite non seulement les afchages, mais aussi les variables et leurs valeurs

10 L’invite peut être In [1]: si iPython est installé — le fonctionnement reste similaire.

Édition dans Python Tutor

Page 9: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

I - Introduction page 9/73 Algorithmique-Programmation

courantes. Le bouton Back permet de revenir à la ligne précédemment exécutée en remetant les variables dans l’état où elles étaient (cet outil d’enseignement met en place toute une infrastructure pour cela, en exécution normale on ne peut pas revenir en arrière).

Merci à Philip J. Guo pour cet excellent outil.

I.4.f - Exécuter des programmes PythonÀ partir de l’IDE que vous avez choisi, ouvrez le fchier script contenant le programme à exécuter et demandez son exécution directement via les commandes dans l’IDE :

• Avec Pyzo, menu Exécuter → Démarrer le script (raccourci E), qui a l’avantage de redémarrer l’interpréteur Python donc de partir d’un environnement d’interprétation vierge. Attention car Pyzo supporte aussi le raccourci qui exécute le module dans l’interpréteur Python courant mais sans le redémarrer (toutes ce qui a été défni lors des tests précédents reste présent en mémoire).

• Avec IDLE, menu Run → Run module (raccourci ).• Avec PyCharm, menu Run → Run (raccourci ).

Sinon, en ligne de commande vous pouvez directement appeler le programme python (Python 3) en lui donnant comme argument le fchier script à exécuter (dans les exemples toto.py).Si le programme python que vous désirez utiliser est directement accessible (dans le PATH) :laurent@litchi:~$ python3 toto.py

Si vous devez utiliser une installation spécifque de Python, il faut l’indiquer sur la ligne de commande :

laurent@litchi:~$ ./apps/miniconda3/bin/python3 toto.py

I.5 - AlgorithmiqueQand on fait le parallèle avec des recetes de cuisine, ou des notices de montage, dans les algorithmes il va nous falloir pouvoir :

• Spécifer l’ordre dans lequel sont exécutées, une à une, les instructions.

➔ En fonctionnement normal, exécution dans l’ordre de lecture de haut en bas (ça sera pareil pour les programmes).

• Ne réaliser certaines séquences d'ordres que dans des cas particuliers.

➔ Instruction d’exécution conditionnelle de bloc d’instructions suivant un test logique.

• Répéter un certain nombre de fois certaines séquences d'ordres.

➔ Instructions de boucle sur un bloc d’instructions, soit tant qu’un test logique est vrai, soit lié à plusieurs données à traiter de façon similaire.

Page 10: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

I - Introduction page 10/73 Algorithmique-Programmation

• Identifer les données que l'on va manipuler (algorithme générique) et ce que l’on va en faire.

➔ Défnition de noms, les variables, qui identifent symboliquement les données, auxquelles elles ne seront associées que lors de l’exécution.

➔ Spécifcation des types des données manipulées pour savoir ce que l’on peut faire avec.

➔ Moyens de récupérer les données à traiter et de sauvegarder les résultats des traitements.

• Défnir des parties d’algorithme que l’on pourra réutiliser à diférents endroits dans avoir à les re-détailler.

➔ Défnition de procédures et fonctions.

Nous allons voir par la suite l’aspect algorithmique et l’aspect programmation sur ces diférents points.

I.5.a - OrganigrammePour présenter certains éléments d’algorithmique, nous utilisons soit une représentation textuelle en français — assez proche des programmes Python, soit une représentation graphique sous la forme d’or-ganigrammes simplifés qui permetent d’identifer visuellement le déroulement de l’exécution avec des formes reliées par des fèches.

Exemple

Note : La représentation en organigramme peut être très « parlante » et peut aider à comprendre la logique de fonctionnement d’un algorithme. Mais elle devient vite fouillis (« spagheti » avec des fèches dans tous les sens) et peu pratique lorsque l’algorithme prend de l’importance ou qu’on com-mence à défnir et utiliser des fonctions — on la réservera à la compréhension des grands principes et des algorithmes simples.

Graphiques organigramme

Page 11: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

I - Introduction page 11/73 Algorithmique-Programmation

I.6 - Tester un programmeTester un algorithme sur un ordinateur correspond à faire exécuter un programme qui réalise cet algo-rithme en lui fournissant des données de test et à vérifer que les résultats atendus correspondent bien aux données fournies. Pour cela on a généralement des données réduites correspondant à des cas connus ou bien qu’on sait calculer/vérifer à la main.

On dispose en général de plusieurs jeux de tests, avec des données correspondant chacun aux difé-rents cas d’utilisation identifés, incluant les cas où le programme doit détecter des erreurs. Ceci doit permetre de vérifer l’ensemble des instructions du programme11.

I.6.a - Techniques de débogage

Afichages au cours de l’exécutionTechnique simple consistant à ajouter des instructions d’afchage à certains endroits choisis dans le programme afn de vérifer que les données manipulées et les transformations efectuées sont bien celles atendues. Ces afchages devront être mis en commentaire ou bien supprimés une fois que le programme sera au point.

Exécution pas à pasLes IDE fournissent généralement des possibilités d’exécuter les programmes ligne à ligne, avec une pause entre deux instructions pendant laquelle il est possible d’afcher les valeurs des diférentes variables. Ils permetent souvent de placer des points d’arrêts dans le programme, où l’exécution nor-male se met en pause et permet de passer en pas à pas, puis de repasser quand on le veut en exécution normale jusqu’au prochain point d’arrêt.

Voir la documentation de l’IDE utilisé pour savoir comment activer et utiliser cete fonctionnalité.

Tests et assertionsOutre les vérifcations normales permetant de valider les données fournies (cas d’erreur atendus que l’on veut détecter), les langages permetent souvent d’insérer des contrôles de validité (de vérifcations d’assertions12) testant que les données sont bien atendues, respectent bien certaines règles — donc que les transformations efectuées par les instructions produisent bien ce à quoi le programmeur s’atend.

En général ces contrôles peuvent être laissés dans le code du programme, ils sont activés en fonction-nement de débogage (debug) et peuvent être désactivés en fonctionnement optimal (release).

Utilisation d’outils externesEnfn, certains outils externes permetent de travailler soit sur le code du programme pour efectuer des vérifcations statiques plus poussées sur celui-ci que ce que ne fait le compilateur, soit à l’exécution du programme pour tracer les chemins d’exécution et l’impact du programme sur son environnement (occupation mémoire, tests de couverture du code, analyse des performances).

Traitement des erreursLes mécanismes d’indication et de traitement des erreurs diférent suivant les langages de programma-tion.

I.6.b - Erreurs en PythonLorsque Python détecte une erreur soit de syntaxe soit d’exécution, il le signale en procédant à une levée d’exception (ou déclenchement d'exception). Ceci provoque l’arrêt des instructions en cours et le

11 On parle de « tests de couverture », qui doivent permetre d’exécuter toutes les alternatives possibles du programme.12 Le langage Python ofre une instruction assert condition. L’option -O de Python désactive les assertions.

Page 12: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

I - Introduction page 12/73 Algorithmique-Programmation

passage du programme dans des blocs d’instruction spécifques. Nous ne verrons en cours que la levée d’exception (cf. p29), pas leur traitement.

Lecture du “Traceback”Si aucun code de traitement ne bloque une exception, celle-ci fnit par générer l’afchage d’un message d’erreur accompagné d’un retraçage (traceback) des instructions qui ont mené à l’erreur.

Cet afchage commence par le mot Traceback sur la première ligne, suivi de couples de lignes décrivant l’origine des instructions ayant conduit à l’erreur (du plus ancien à celui qui a généré l’erreur), et en dernière ligne une indication de la classe de l’erreur accompagnée d’un message explicatif.

Traceback (most recent call last): File "/.../principal.py", line 42, in <module> print(validation.test(9, 1)) File "/.../validation.py", line 10, in test return 3 * calculs.preparation(x, y) File "/.../calculs.py", line 12, in preparation return 1 + simulrap(a, b-1) File "/.../calculs.py", line 25, in simulrap return abs(x) / (3 * y)ZeroDivisionError: division by zero

Dans cet exemple nous avons eu une division par zéro, au niveau de l’instruction à la ligne 25 du fchier Python calculs.py dans la fonction simulrap (sur une instruction avec une division par 3×y ). Les argu-ments d’appel ont été fournis à cete fonction par la fonction preparation en ligne 12… etc.

Il est nécessaire d’apprendre à lire et décoder ces retraçages afn de savoir déboguer et corriger les pro-grammes.

Page 13: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

II - Types de base page 13/73 Algorithmique-Programmation

II - Types de base

Note : la représentation littérale des valeurs est la forme sous laquelle on les écrit dans les pro-grammes.

II.1 - Nombres

II.1.a - EntiersEn algorithmique on les choisira par exemple pour du dénombrement, du comptage.

En Python on utilise le type de données int. La représentation litérale utilise simplement des chifres en base 10 avec un signe optionnel :

>>> 00>>> type(0)<class 'int'>>>> 11>>> 144144>>> -321-321>>> +51+51

La fonction standard int() permet dans un programme de convertir une représentation textuelle d’un nombre vers l’entier correspondant. Il est aussi possible avec int() de convertir n’importe quelle valeur compatible en une valeur entière.

>>> int('0')0>>> int('-12')-12>>> int('48')48>>> int(3.712) # Conversion d'un nombre réel en nombre entier3

II.1.b - Flotants (réels)En algorithmique ils sont généralement choisis pour des mesures de grandeurs physiques, du calcul numérique.

On utilise souvent le terme fottant (foat) pour « nombre décimal à virgule fotante ».

En Python on utilise le type de données float. La représentation litérale combine un signe optionnel, les chifres qui forment le nombre, avec un point obligatoire (.) pour la virgule décimale, et éventuelle-ment un E ou un e suivi d’une puissance de 10.

>>> 0.00.0>>> type(0.0)<class 'float'>>>> 12.76512.765>>> .320.32>>> -45.84-45.84

Page 14: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

II - Types de base page 14/73 Algorithmique-Programmation

>>> 1e61000000.0>>> -3.14e2-314.0>>> 8.6592E-108.6592e-10>>> 8.6592E-40.00086592

La fonction standard float() permet dans un programme de convertir une représentation textuelle d’un nombre vers le fotant correspondant.

>>> float('0')0.0>>> float('0.425')0.425>>> float('-23E-10')-2.3e-09

Attention : La représentation en mémoire des fotants impose des limites13 et provoque des pertes de précision lors des calculs. Par exemple :>>> 1e20 + 1 - 1e20 # Notez la perte de 1 devant 1020

0.0>>> 0.1 * 0.1 * 0.1 # Notez l'apparition du chiffre 2 en 19ème décimale0.0010000000000000002

II.1.c - Opérations sur les nombresOn utilise en algorithmique les opérations que l’on pratique couramment en mathématiques ou en phy-sique pour manipuler des valeurs numériques : addition, soustraction, multiplication, division, éléva-tion à une puissance, valeur absolue, division euclidienne (entière) et reste… On peut utiliser des paren-thèses pour regrouper des parties d’expression et modifer les priorités des opérateurs.

En Python on dispose d’opérateurs (caractères ayant une signifcation particulière) et de fonctions dédiées, utilisables indiféremment avec les nombres entiers ou fotants qui peuvent être combinés dans les expressions de calcul14 :

>>> 28 + 2 # Addition, opérateur +30>>> 28 + 2.0 # Résultat flottant dès qu'il y a un flottant dans l'opération!30.0>>> 18 - 9 # Soustraction, opérateur -9>>> 45 * 3 # Multiplication, opérateur *135>>> 20 / 3 # Division flottante (même avec des entiers!)15

6.666666666666667# Division entière de l'exemple: 20 = 3 * 6 + 2>>> 20 // 3 # Division entière (dite euclidienne), opérateur //6>>> 20 % 3 # Reste de la division entière, opérateur %2>>> 5 ** 3 # Élévation à la puissance, opérateur **125>>> 2 ** 0.51.4142135623730951>>> pow(0.5, 4) # Fonction élévation à la puissance0.0625>>> abs(-3.5) # Fonction valeur absolue3.5>>> round(34.6732, 1) # Fonction arrondi à n décimales34.7

Priorité dans les expressions mathématiques (opérateurs associatifs de gauche à droite sauf si précisé) :

1. Expressions parenthésées (…)2. Accès aux valeurs des variables (x, x.nom, x[index]…, fonction(x))

13 Comptez ~15 chifres décimaux signifcatifs et des ordres de grandeur jusqu’à 10±308.14 Il existe aussi des opérateurs, que nous ne détaillerons pas ici, travaillant directement au niveau des bits des entiers.15 Atention, dans la plupart des langages une division d’entiers donne un résultat entier ⇒ 1/2→0

Page 15: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

II - Types de base page 15/73 Algorithmique-Programmation

3. Opérateur élévation à une puissance ** (associatif de droite à gauche)4. Opérateurs unaires positif/négatif + -5. Opérateurs de multiplication/division * / // %6. Opérateurs d’addition/soustraction + -

Exemples de parenthésage d’expressions :

>>> 4 + 3 * 5 ** 279>>> (4 + 3) * 5 ** 2175>>> ((4 + 3) * 5) ** 21225>>> 4 + (3 * 5) ** 2229

Attention, en Python la notation de parenthèses contenant des virgules de séparation est la défnition d’un tuple (conteneur permetant de regrouper plusieurs valeurs).

>>> (4 + 3, 5 ** 2)(7, 25)

Si vous voyez apparaître des erreurs du genre TypeError metant en cause un 'tuple', vous avez peut-être une expression parenthésée contenant une virgule involontaire.

Fonctions mathématiquesLes fonctions mathématiques usuelles sont accessibles via une librairie particulière disponible en stan-dard, le module math. Il faut importer ce module (ou bien directement les fonction de ce module) pour pouvoir les utiliser. Ce module contient aussi la défnition des valeurs de pi et e. Les fonctions s’ap-pliquent à des valeurs numériques entières ou fotantes, les angles sont exprimés en radians.

>>> from math import pi, e, sin, cos, tan, degrees, radians, log, log10, sqrt, acos, asin, atan, acos, asin, atan, atan2, floor, ceil, trunc, hypot>>> pi # Rapport du périmètre d'un cercle sur son diamètre3.141592653589793>>> e # Valeur de la base des logarithmes naturels (népériens)2.718281828459045>>> sin(pi/4) # Fonction sinus0.7071067811865475>>> cos(1) # Fonction cosinus0.5403023058681398>>> tan(pi/4) # Fonction tangente0.9999999999999999>>> degrees(2*pi) # Fonction conversion radians → degrés360.0>>> radians(90) # Fonction conversion degrés → radians1.5707963267948966>>> log(1) # Fonction logarithme naturel (népérien, base e)0.0>>> log(e)1.0>>> log(e ** 2)2.0>>> log10(1) # Fonction logarithme base 100.0>>> log10(1000)3.0>>> sqrt(2) # Fonction racine carrée1.4142135623730951>>> sqrt(81)9.0>>> acos(0.5) # Fonction arc cosinus1.0471975511965979>>> asin(1) # Fonction arc sinus1.5707963267948966>>> atan(1) # Fonction arc tangente0.7853981633974483

Page 16: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

II - Types de base page 16/73 Algorithmique-Programmation

>>> atan2(-3,-4) # Fonction arc tangente x/y (considère signes de x et de y)-2.498091544796509>>> floor(23.78) # Fonction arrondi à l'entier immédiatement inférieur ou égal23>>> ceil(23.78) # Fonction arrondi à l'entier immédiatement supérieur ou égal24>>> trunc(23.67672) # Fonction troncature à la partie entière seulement23>>> hypot(4,3) # Fonction hypothénuse √(x²+y²)5.0

Pour les tests d’égalités entre nombres fottants Python fournit une fonction isclose()16 :

>>> from math import isclose>>> 0.1 * 0.1 * 0.1 == 0.001False>>> isclose(0.1 * 0.1 * 0.1, 0.001)True

II.2 - Valeurs logiquesL’algèbre de Boole17 considère deux valeurs de vérité, vrai et faux. Elle est utilisée couramment, non seulement en mathématiques, mais aussi dans la vie de tous les jours. Elle se retrouve naturellement dans les algorithmes.

En algorithmique on utilise simplement des valeurs Vrai et Faux.

En Python on utilise le type de données bool dont il existe deux valeurs litérales : False et True.

>>> True # Constante booléenne vraiTrue>>> False # Constante booléenne fauxFalse>>> type(True)<class 'bool'>

II.2.a - Opérations booléennes

ComparaisonsOn obtient souvent des valeurs logiques simplement en comparant des valeurs d’autres types entre elles — il faut bien sûr que ces types soient comparables, que cela ait un sens.

Tous ces opérateurs de comparaison et de relation d’ordre, fournissent un résultat booléen :

>>> 34 == 2 * 17 # Opérateur test d'égalité ==True>>> 27 != 3 * 9 # Opérateur test de différence !=False>>> 56 < 12 # Opérateur test strictement inférieur <False>>> 56 <= 2 * 28 # Opérateur test inférieur ou égal <=True>>> 45 > 4 * 5 # Opérateur test strictement supérieur >True>>> 23 >= 25 # Opérateur test supérieur ou égal >=False

Notez le double == pour la comparaison testant l’égalité, et le != pour la comparaison testant la difé-rence. Ces opérateurs de comparaison sont moins prioritaires que les opérateurs mathématiques.

Python peut réaliser la conversion directe implicite de nombreuses valeurs vers les booléens, ce qui peut causer certaines incompréhensions. Pour le cours nous passerons explicitement par des opéra-tions de comparaison pour obtenir des booléens.

16 Pour tester l’égalité de x avec 0, il faut tester l’égalité de x+1 avec 1.17 Du logicien, mathématicien et philosophe Britannique George Boole (1815-1864).

Page 17: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

II - Types de base page 17/73 Algorithmique-Programmation

Algèbre de BooleIl existe trois opérateurs logiques fondamentaux, disponibles en Python :

• Le NON, ou négation, inverse la valeur logique. En Python c’est l’opérateur not :

x not xFalse True

True False

• Le ET, ou conjonction, fournit une valeur vraie lorsque tous ses opérandes sont vrais. En Python c’est l’opérateur and :

x y x and yFalse False False

False True False

True False False

True True True

• Le OU, ou disjonction, fournit une valeur vraie lorsque au moins un de ses opérandes est vrai. En Python c’est l’opérateur or.

x y x or yFalse False False

False True True

True False True

True True True

Priorité : ces 3 opérateurs booléens sont moins prioritaires que les opérateurs de comparaison et opéra-teurs mathématiques, et sont évalués dans l’ordre : 1) not, 2) and, 3) or. En cas de doute, n’hésitez pas à utiliser des parenthèses.

À partir de ces trois relations logiques fondamentales l’algèbre de Boole défnit une série de relations composées que nous ne détaillerons pas ici.

Les opérateurs de base possèdent plusieurs propriétés intéressantes pour transformer et/ou simplifer des expressions logiques, outre la commutativité, l’associativité, et la distributivité entre ET et OU, citons :

Propriété ET OUÉlément neutre True and x ⇔ x False or x ⇔ x

Élément absorbant False and x ⇔ False True or x ⇔ TrueSimplifcation x and (not x or y) ⇔ x and y x or (not x and y) ⇔ x or y

Complémentaire x and not x ⇔ False x or not x ⇔ TrueLes Lois de De Morgan ofrent un outil supplémentaire de transformation lorsqu’on a une négation de ET ou une négation de OU.

not (x or y) ⇔ (not x) and (not y)

not (x and y) ⇔ (not x) or (not y)

II.3 - TextesAussi appelés chaînes de caractères (raccourci en « chaîne ») ou encore séquences de caractères ; où chaque symbole du texte est représenté par un caractère : letres alphabétiques, chifres, marques syn-taxiques, espaces…

En algorithmique on manipule du texte dès que l’on a des données liées à la langue, que ça soit un caractère, un nom, un mot, une phrase ou encore un texte complet. Dans la description d’un algorithme on note généralement les textes entre guillemets “…” (éventuellement des chevrons «… »).

Page 18: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

II - Types de base page 18/73 Algorithmique-Programmation

En Python on utilise le type de données str qui stocke les chaînes sous la forme de séquences de carac-tères (comme tout est numérique, sous la forme d’entiers correspondant à des codes de caractères). Les valeurs litérales sont écrites entre des couples de guillemets " ou bien des couples d’apostrophes ' (uti-liser l’un permet de metre l’autre dans le texte), sur la même ligne.

Le caractère \, ou backslash, est appelé caractère d’échappement. Combiné à d’autres caractères, il per-met de spécifer des notations particulières dans une chaîne — voir tableau ci-après.

Note : dans les exemples ci-après on passe par print() pour éviter que l’interpréteur Python n’afche la forme litérale de la chaîne.

>>> print("") # Chaîne vide (contient 0 caractère)

>>> print("A") # Chaîne d'un seul caractère18

A>>> print("Un texte simple")Un texte simple>>> print('Un autre')Un autre>>> print("Avec l'inclusion de \"guillemets\" et de \\ dans le texte")Avec l'inclusion de "guillemets" et de \ dans le texte>>> print("Sur\nplusieurs\nlignes")Surplusieurslignes>>> print("Du texte\n\tavec des tabulations\n\td'alignement")Du texte avec des tabulations d'alignement>>> print("Caractère OE liés par son code \u0152")Caractère OE liés par son code Œ>>> print("Caractère pi par son nom \N{GREEK SMALL LETTER PI}")Caractère pi par son nom π

Il est aussi possible d’exprimer une chaîne en utilisant des paires de triples guillemets ou des paires de triples apostrophes. Cete syntaxe permet de placer, sans échappement, des retours à la ligne (ainsi que des " et ') dans la chaîne.

>>> print("""Une chaine "texte" sur plusieurs lignes, - où tous les caractères - comptent jusqu'au triplet de fermeture""")Une chaine "texte" surplusieurs lignes, - où tous les caractères - comptent jusqu'au tripletde fermeture

La fonction str() permet de convertir la plupart des valeurs en leur représentation sous forme de texte :

>>> str(184) # Conversion nombre entier en chaîne'184'>>> str(3.14) # Conversion nombre flottant en chaîne'3.14'>>> str(True) # Conversion booléen en chaîne'True'

Qelques séquences utiles avec le caractère d’échappement :

Séquence Usage\\ Insère un simple \\" Insère un " (utile dans une chaîne entre ")\' Insère un ' (utile dans une chaîne entre ')

18 Là où Python utilise une chaîne d’un caractère lorsqu’il n’y a qu’un caractère à traiter, la plupart des langages ont un type caractère spécifque.

Page 19: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

II - Types de base page 19/73 Algorithmique-Programmation

Séquence Usage\n Insère un retour à la ligne (line feed, code 10)\r Insère un retour chariot (carriage return, code 13)\t Insère une tabulation horizontale (code 9)\f Insère un saut de page (form feed, code 12)

\xhh Où hh sont 2 chifres hexadécimaux, insère le caractère correspondant au code unicode sur 2 chifres

\uhhhh Idem avec 4 chifres hexadécimaux\Uhhhhhhhh Idem avec 8 chifres hexadécimaux\N{nom} Insère le caractère correspondant au nom unicode

II.3.a - Opérations sur les chaînesEn algorithmique les opérations de base sur les chaînes doivent permetre au moins la concaténation (mise bout à bout), d’en connaître la longueur (nombre de caractères) et de pouvoir réaliser l’extrac-tion d’une partie de chaîne (sur une longueur à partir d’une position). On considère généralement qu’une série d’opérations de plus haut niveau sont également disponibles (recherche de sous-chaîne, conversion minuscule/majuscule, découpage sur un caractère séparateur…).

En Python, une fois constituée en mémoire, une chaîne n’est plus modifable, il faut en construire une nouvelle qui inclue les modifcations voulues. On dit que les chaînes Python sont immuables19. Toutes les opérations de modifcation sur les chaînes produisent donc de nou-velles chaînes.

L’opérateur + entre deux chaînes permet la concaténation de celles-ci. L’opérateur * entre une chaîne et un nombre entier permet la répétition de la chaîne. La fonction len() permet de connaître la longueur (nombre de caractères) d’une chaîne.>>> "Je programme" + " en Python" # Concaténation'Je programme en Python'>>> "Répéter " * 6 # Répétition'Répéter Répéter Répéter Répéter Répéter Répéter '>>> len("Le langage Python") # Longueur17

Les comparaisons entre chaînes sont réalisées simplement en comparant consécutivement les codes des caractères de même index dans les deux chaînes — de tous les caractères, espaces et symboles compris. La première diférence donne la relation d’ordre. Si une chaîne a été complètement parcourue et pas l’autre, alors l’autre est « plus grande ».>>> "Hello" == "Hello"True>>> "Hello" == " Hello " # Blancs significatifs pour la comparaisonFalse>>> "Hello" > "Hella" # Caractère a final dans la seconde chaîne < caractère oTrue>>> "Hello" < "Hello you" # Seconde chaîne identique au début, mais plus longueTrue

Deux fonctions, chr() et ord(), permetent de passer du code au caractère et vice-versa.

>>> chr(937) # Code → caractère'Ω'>>> ord('Ω') # Caractère → code937

Un truc pratique : les codes de a à z sont consécutifs, les codes de A à Z sont consécutifs, et les codes de 0 à 9 sont consécutifs.

>>> ord('a'), ord('b'), ord('c'), '…', ord('z')

19 Dans d’autres langages les chaînes créées peuvent être modifées, élément à prendre en compte lors de la programmation. On trouve aussi souvent l’anglicisme « immutable »

Page 20: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

II - Types de base page 20/73 Algorithmique-Programmation

(97, 98, 99, '…', 122)

II.3.b - Indexation et sous-chaînesEn Python les chaînes peuvent être considérées comme des tableaux de caractère indicés par leur position, en commençant à l’indice 0 pour le premier. L’utilisation de l’opérateur [] permet d’ex-traire un caractère particulier (syntaxe [indice]) ou bien d’extraire une sous-chaîne (syntaxe [début:fn]) — on parle de tranche ou slice.

Dans les exemples ci-après, pour des facilités d’écriture, nous utilisons une variable s associé à une chaîne. De plus, nous utilisons la notation programmation objet d’appel aux méthodes des chaînes avec s.nomméthode() (les méthodes sont comme des fonctions, elles travaillent sur la donnée indiquée avant le ., ici la chaîne associée à s) :

>>> s = "la chaine, Du texte" # Chaîne de départ#indices: 111111111# 0123456789012345678>>> s[0] # Extraction premier caractère'l'>>> s[1] # Extraction second caractère'a'>>> len(s) # Longueur de la chaîne19>>> s[18] # Extraction dernier caractère'e'>>> s[19] # Extraction impossible (erreur) après le dernier caractèreTraceback (most recent call last): File "<stdin>", line 1, in <module>IndexError: string index out of range>>> s[-1] # Extraction du dernier caractère en parcours inversé (← index négatif)'e'>>> s[-2] # Extraction de l'avant dernier caractère en parcours inversé't'>>> s[0:len(s)] # Extraction sous-chaîne indice du début à indice de la fin'la chaine, Du texte'>>> s[11:13] # Extraction sous-chaîne indices 11 compris à 13 non compris'Du'>>> s[14:] # Extraction sous-chaîne indices 14 jusqu'à la fin'texte'>>> s[:3] # Extraction sous-chaîne du début jusqu'à l'indice 3 non compris'la '>>> s[14:-2] # Extraction sous-chaîne indice 14 compris à -2 (←) non compris'tex'>>> s[:] # Extraction sous-chaîne du début à la fin'la chaine, Du texte'

II.3.c - Méthodes sur les chaînesRecherches20 diverses avec les méthodes count(), find(), index(), startswith(), endswith() et l’opé-rateur in.

>>> s = "la chaine, Du texte" # Rappel de la chaîne de départ>>> s.count('e') # Nombre d'exemplaires d'un caractère3>>> s.count('o')0>>> s.count('te') # Nombre d'exemplaires d'une sous-chaîne2>>> s.find('Du') # Recherche indice d'une sous-chaîne11>>> s.find('une') # …indice négatif car absente-1>>> s.index('Du') # Indice du début d'une sous-chaîne11>>> s.index('une') # …pas possible (erreur) car absenteTraceback (most recent call last): File "<stdin>", line 1, in <module>

20 Certaines méthodes prennent des paramètres supplémentaires permetant de spécifer des indices début/fn à considérer. Il existe aussi des méthodes qui recherchent en sens inverse, en commençant par la fn.

Page 21: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

II - Types de base page 21/73 Algorithmique-Programmation

ValueError: substring not found>>> s.startswith('Une') # Présence sous-chaine au débutFalse>>> s.endswith("xte") # Présence sous-chaine à la finTrue>>> 'Du' in s # Opérateur de test de présence inTrue>>> 'une' in sFalse>>> 'toto' not in s # Opérateur de test d'absence not inTrue

Remplacement et nettoyage21 avec les méthodes replace(), et strip().

>>> s = "la chaine, Du texte" # Rappel de la chaîne de départ>>> s.replace("la", "Une")'Une chaine, Du texte'>>> s.replace("e", "$$")'la chain$$, du t$$xt$$'>>> s.replace(' ', '') # Remplacement espace par vide → suppression'lachaine,Dutexte'>>> s.strip("la te") # Suppression d'occurences de caractères au début/fin'chaine, du tex'>>> s2 = " avec des blancs \n\t " # Autre chaîne, contenant des blancs au début/fin>>> s2.strip() # Suppression des blancs au début et à la fin'avec des blancs'

Changement de casse (minuscules/majuscules) :

>>> s = "la chaine, Du texte" # Rappel de la chaîne de départ>>> s.upper() # Tout en majuscules'LA CHAINE, DU TEXTE'>>> s.lower() # Tout en minuscules'la chaine, du texte'>>> s.title() # Première lettre de chaque mot en majuscule'La Chaine, Du Texte'>>> s.capitalize() # Première lettre de la chaîne en majuscule'La chaine, du texte'>>> s.swapcase() # Inversion minuscule/majuscule'LA CHAINE, dU TEXTE'

Découpage d’une chaîne en plusieurs sous-chaînes, avec la méthode split() :

>>> s.split() # Par défaut découpe sur les blancs['la', 'chaine,', 'Du', 'texte']>>> s.split(',') # Peut découper sur un caractère spécifique['la chaine', ' Du texte']

Le résultat de ce découpage est un tableau (list) de chaînes, notion abordée plus loin.

Regroupement des éléments d’un tableau de chaînes avec un séparateur, avec la méthode join() appliquée à la chaîne contenant le séparateur et ayant comme argument un tableau (list) de chaînes :

>>> lsMots = ['un', 'pour', 'tous', 'tous', 'pour', '1']>>> ' '.join(lsMots) # Séparateur caractère espace'un pour tous tous pour 1'>>> '+++'.join(lsMots) # Séparateur plusieurs caractères quelconques'un+++pour+++tous+++tous+++pour+++1'>>> ''.join(lsMots) # Séparateur chaine vide'unpourtoustouspour1'

Le formatage de chaînes à partir d’autres valeurs est abordé dans la section Formatage des valeurs en page 27.

Des tests sur les caractères peuvent être efectués avec une série de méthodes isxxx() afn de connaître la classifcation des caractères d’une chaîne :

>>> 's'.isupper()False>>> 's'.islower()True

21 Certaines méthodes prennent des paramètres supplémentaires permetant de spécifer le nombre de remplacement à efectuer. Il existe aussi des méthodes qui travaillent spécifquement sur le début ou bien sur la fn de la chaîne.

Page 22: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

II - Types de base page 22/73 Algorithmique-Programmation

>>> 's'.isalpha()True>>> 'toto3'.isalnum()True>>> '\t'.isspace()True>>> '3'.isdigit()True>>> '338'.isdecimal()True

II.3.d - Modification d’une chaîneLes chaînes étant immuables, il faut passer par une ré-afectation de la variable avec la nouvelle valeur modifée (voir « Variables et afectation » ci-après).

>>> s = "la chaine, Du texte">>> s = s.upper()>>> s'LA CHAINE, DU TEXTE'

Page 23: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

III - Variables et afectation page 23/73 Algorithmique-Programmation

III - Variables et afectation

Afn de référencer des données, des fonctions, des bibliothèques de code, des classes, etc. les langages utilisent des noms ou identifcateurs. Leur forme doit se conformer à certaines règles syntaxiques liées au langage, décrites ci-après, auxquelles nous ajouterons des conventions pour le cours.

Les variables sont des noms qui référencent des données.

L’afectation ou assignation (assignment en anglais) est l’opération qui associée un nom avec une donnée.

III.1 - Instruction d’afectationC’est un ordre donné dans le programme d’associer une donnée en mémoire à un nom.

En algorithmique on peut l’écrire nom ← valeur. On dit que le nom “reçoit” la valeur, ou encore que le nom est “valorisé” à la valeur.

La valeur peut être simplement une valeur litérale, mais elle peut aussi être une expression comportant des opérations de calculs entre diférentes valeurs et/ou variables. Dans ce cas l’expression en partie droite est d’abord évaluée (calculée) et c’est le résultat de cete évaluation qui est associée au nom en partie gauche.

nom ← «Python»age ← 23annais ← 2019 - 23

En Python on écrit nom = valeur.

sNom = "Python"iAge = 23iAnNais = 2019 - 23

Une nouvelle valeur peut être associée ultérieurement à une variable existante en exécutant à nouveau une instruction d’afectation.

iAge = 42

L’ancienne valeur est alors perdue (sauf si elle a été mémori-sée avec une autre variable).

Python étant dynamiquement typé, la variable prend auto-matiquement le type de la valeur qu’on lui a afecté. Ce n’est pas le cas des nombreux langages statiquement typés, et pour apprendre la programmation ça peut être un piège — dans le cadre du cours nous apportons plus loin des restrictions à ce que nous autorisons avec les variables.

III.1.a - Utilisation des variablesÀ partir du moment où une variable a été défnie avec une valeur, elle peut être utilisée n’importe où à la place d’une valeur litérale ou d’une expression.

iAge = 23 # iAge ← 23iAnNais = 2019 - iAge # iAnNais ← résultat du calcul: 1996iAge = 12 # iAge ← 12print(iAnNais) # affiche 1996, iAnNais n'a pas changé

Page 24: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

III - Variables et afectation page 24/73 Algorithmique-Programmation

Une fois réalisée l’afectation du résultat d’une expression à une variable, celle-ci devient indépendante du contenu de l’expression22. Dans l’exemple donné, quand on modife ensuite la variable iAge, la variable iAnNais ne change pas.

Même variable des deux côtésUne variable peut être utilisée des deux côtés d’une afectation, en partie droite comme valeur à utiliser dans une expression, et en partie gauche comme variable où stocker le résultat de l’évaluation de l’ex-pression. L’évaluation se fait avant l’afectation, donc avant que la variable ne soit modifée.

>>> x = 23>>> x = 2 * x - 10>>> x36>>> x = x + 1 # Incrémentation>>> x37>>> x = x - 1 # Décrémentation>>> x36

L’instruction d’afectation = n’est pas l’opérateur d’égalité mathématique.

III.1.b - ConstantesCe sont des noms auxquels sont associées des valeurs qui ne changent pas au cours de l’exécution du programme. Elles donnent un sens aux données (par exemple TAUX_TVA au lieu de 20.6), facilitant la compréhension du programme. Elles facilitent les évolutions du programme (si le taux de TVA change un jour, on change simplement à l’endroit où la constante est défnie).

III.1.c - Afectations multiplesEn Python, lorsqu’il y plusieurs valeurs à afecter à plusieurs variables, cela peut se faire en une seule instruction d’afectation. Les variables en partie gauche sont séparées par des virgules. Les valeurs (ou expressions) en partie droite sont aussi séparées par des virgules23. Il y a autant de valeurs que de variables.

sNom, iAge = "Python", 23

Note : Nous utiliserons l’afectation multiple avec les fonctions retournant plusieurs valeurs.

III.2 - Noms des identificateurs

III.2.a - Règles généralesLes noms doivent permetre de comprendre ce à quoi ils sont associés, ce qu’ils représentent. Pour vous et pour les lecteurs de vos programmes, la compréhension du sens doit être simple et sans ambi-guïté.

Les noms :

• commencent par un caractère alphabétique24 ou par un caractère _ (appelé “souligné” ou “barre du bas” ou underscore)

• se continuent éventuellement par des caractères alphabétiques, numériques, ou _.

• ne doivent pas être des mots réservés du langage (voir « Mots clés du langage » page 7).

Exemples de noms valides en Python : x2, hauteur, calculer_maxi, bDebut, HAUTEUR, _mini, Pt_X, distance_cm, xStartT0.

22 Contrairement aux expressions dans les cellules d’un tableur, dont la valeur résultat est ré-évalué lorsqu’une cellule référencée dans l’expression change.

23 On peut aussi les entourer par des parenthèses. On manipule ainsi un tuple Python, type qui ne sera pas détaillé.24 Au sens large, les alphabets cyrilliques, grecs, les kanjis, les marques diacritiques (accents…), etc, sont autorisés en Python.

Page 25: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

III - Variables et afectation page 25/73 Algorithmique-Programmation

Exemples de noms invalides en Python : 2x, temp°C, for, as.

Python fait la distinction de casse (distinction minuscules vs majuscules). Par exemple les noms maxi, Maxi, MAXI, MaXi , MaxI sont diférents, ils peuvent coexister en référençant des données diférentes.

Restrictions pour le coursLimitation aux caractères alphabétiques latins sans accent et sans commencer un nom par le carac-tère _ (sauf quelques cas spécifés).

Utilisation de la convention Python d’écrire les constantes toutes en majuscules (ex. TAUX_TVA, MAX_X) et il interdiction de les modifer.

Défnition des noms des fonctions tout en minuscules avec les mots séparés par des _.

III.2.b - Conventions pour l’apprentissageLe langage Python est très dynamique, il permet au cours de l’exécution d’associer un nom à une don-née (ou fonction ou module ou objet…) et de changer ensuite pour associer ce nom à une autre donnée de n’importe quel type. Si ceci est pratique pour du développement rapide de scripts et quand on a l’ha-bitude, ça peut être très “piégeant” en phase d’apprentissage lorsqu’on débute en programmation.

Chaque variable ne sera utilisée qu’avec des données du même type. Il sera par exemple interdit de lire une chaîne "42" et la stocker dans une variable pour ensuite convertir cete valeur en entier 42 et la stocker dans la même variable.

Nous ne suivrons pas dans ce cours les conventions de nommage de Python (cf. le PEP825) mais nos propres règles. Pour bien préciser les types de données que nous voulons lier aux variables, nous met-rons en œuvre ce semestre la « notation hongroise » pour le nommage des variables, qui précise le type de la variable au début de son nom, ainsi que des sufxes pour les variables globales et pour les paramètres.

Notation hongroisePour cours/TDs/TP : préfxes de type pour les variables — on s’interdit de stocker dans ces variables toute donnée d’un autre type que celui indiqué par le préfxe !

Préfxe de type Pour le typei entier (int)f nombre réel (nombre à virgule fotante — float)b booléen (valeur logique True/False — bool)s chaîne de caractère (str)l liste de valeurs (tableau indicé — list)

fic objet fchier résultant d’un appel à open()o objet d’une classe défnie par nous en programmation objet

On utilisera la notation « mixed case », mélangeant minuscules et majuscules, afn d’identifer mieux la partie sémantique dans le nom de la variable.

Exemples :• iCompteur : valeur entière (comptant quelque chose)• fCoef : valeur fotante (un coefcient)• iAge : valeur entière (age d'une personne)• sDateDebut : chaîne de caractères (représentant une date de démarrage)• ficDataLect : fchier (contenant des données à lire)• oPtDepart : objet point (pour des coordonnées de départ)

25 Voir https://www.python.org/dev/peps/pep-0008/#naming-conventions

Page 26: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

III - Variables et afectation page 26/73 Algorithmique-Programmation

• liAnnees ; liste d’entiers (représentant des années)

Sufixes globales et paramètresÀ partir du moment où nous écrirons des fonctions : sufxes de portée pour les variables globales et pour les paramètres des fonctions. Ceux-ci aideront à comprendre la portée des variables, à savoir où elles sont utilisables dans le programme.

Sufxe de portée Pour la portée_g globale, reçoit une valeur directement au niveau du module_p paramètre d’une fonction, recevra les valeurs transmises lors des appels

à la fonction

Exemples :

• iCompteur_g : globale compteur entier• sNom_g : chaîne globale contenant un nom• fx_p : paramètre fotant x• iMax_p : paramètre maximum entier• lPoints_p : paramètre liste de points• iCpt : variable locale entière

Page 27: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

IV - Afchage et saisie page 27/73 Algorithmique-Programmation

IV - Afichage et saisie

IV.1 - Fonction d’afichageLa fonction standard print() est directement accessible (builtin). Elle prend un nombre variable d’argu-ments26, séparés par des virgules, qu’elle afche sous forme de texte lisible, en les séparant par des espaces et en terminant par un retour à la ligne. Ces arguments peuvent être des valeurs litérales, des variables, ou toute expression permetant de calculer un résultat. Un exemple avec un script et son exé-cution :

sLang = "Python"iNais = 1991iAge = 2019 - iNaisprint("Le langage", sLang, "a", iAge, "ans.")print("En 2030 il aura", 2030 - iNais, "ans.")

Le langage Python a 28 ans.En 2030 il aura 39 ans.

Utilisée sans argument, la fonction print() produit juste l’afchage d’un retour à la ligne.

>>> print()

Pour contrôler plus fnement l’afchage, on utilisera un formatage de chaînes comme indiqué ci-des-sous.

IV.1.a - Formatage des valeursPour ce cours nous utilisons les chaînes littérales de formatage27 (ou f-string) apparues dans Python 3.6. Ce sont des chaînes de caractères dont la déclaration est préfxée par un f (f"…"), et qui peuvent comporter des « champs » indiqués entre accolades. Ces champs peuvent contenir des variables ou des expressions dont la valeur est évaluée au moment où l’exécution du programme construit la chaîne.

En reprenant l’exemple précédent, les variables et autres arguments que l’on donnait à print() sont maintenant directement dans la chaîne de formatage, entre {} :

sLang = "Python"iNais = 1991iAge = 2019 - iNaisprint(f"Le langage {sLang} a {iAge} ans.")print(f"En 2030 il aura {2030-iNais} ans.")

Le langage Python a 28 ans.En 2030 il aura 39 ans.

Dans l’expression entre {}, il est aussi possible de metre des expressions, d’appeler des fonctions ou d’accéder à des noms dans des modules :

import mathfSomme = 256.23iNbValeurs = 12print(f"La moyenne entière est {int(fSomme/iNbValeurs)}.")print(f"Les sinus de e={math.e} est {math.sin(math.e)}")

26 La fonction print() accepte en plus trois arguments fnaux nommés (end=, sep=, fle=) que nous ne traiterons pas ici.27 Il existe aussi en Python l’opérateur % ainsi que la méthode format() des chaînes, que vous avez peut-être déjà vu ailleurs.

Page 28: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

IV - Afchage et saisie page 28/73 Algorithmique-Programmation

La moyenne entière est 21.Les sinus de e=2.718281828459045 est 0.41078129050290885

Options de formatageDans les champs entre accolades, après l’indication de la variable ou expression à afcher, on peut spé-cifer la largeur de formatage et un alignement ainsi qu’un caractère de remplissage, forcer l’apparition du signe d’un nombre même s’il est positif, limiter le nombre de décimales et la notation d’un fotant, spécifer la base d’un entier…

Syntaxe : {donnée : remplissage alignement signe larg.mini . précision.ou.larg.maxi type }

Voici quelques exemples :

fVal = 123.456789e5fValNeg = -34.56789012iEntier = 100sLang = "Python"print(f"Flottant: {fVal:.3f} {fVal:.3e} {fVal:.3g} {fVal:%}")print(f"Flottant: {fVal:+3.2f} {fValNeg:3.2f}")print(f"Entier: binaire {iEntier:b} décimal {iEntier:d}")print(f"hexadécimal {iEntier:x} caractère {iEntier:c}")print(f"Chaîne: [{sLang:<10}] [{sLang:>10}] [{sLang:^10}] {sLang:*^10} [{sLang:5.5}]")print(f"Représentation chaîne: {sLang!r}")print(f"Résultat: {iEntier:=^10}")

Et le résultat :

Flottant: 12345678.900 1.235e+07 1.23e+07 1234567890.000000%Flottant: +12345678.90 -34.57Entier: binaire 1100100 décimal 100Entier: hexadécimal 64 caractère dChaîne: [Python ] [ Python] [ Python ] **Python** [Pytho]Représentation chaîne: 'Python'Résultat: ===100====

IV.2 - Fonction de saisieLa fonction standard input() est directement accessible (builtin). Elle prend un argument chaîne de caractères qui est afchée afn de donner des indications à l’utilisateur28. Elle met en pause l’exécution du programme en atendant que l’utilisateur réalise une saisie au clavier, fnalement validée par l’appui sur la touche . La fonction input() fournit un résultat, elle retourne une chaîne de caractères contenant ce que l’utilisateur a saisi. Il faut éventuellement efectuer une conversion de type sur ce résultat.

Exemple de programme (notez les conversions de types de valeurs) :

sNom = input("Votre nom ? ")print(f"Bonjour, {sNom}")sMois = input("N° du mois en cours :") # Saisie mois dans variable chaîne intermédiaireiMois = int(sMois) # Conversion chaîne mois en entieriAnnee = int(input("Année en cours :")) # Saisie année et conversion directe en entierprint(f"XX/{iMois}/{iAnnee}")

À l’exécution (saisies de l’utilisateur en gras — notez qu’une chaîne d’indication en argument à l’appel de input() permet de faire la saisie à la suite sur la même ligne) :

Votre nom ? LaurentBonjour, LaurentN° du mois en cours :1Année en cours :2019XX/1/2019

28 Bien que cet argument soit optionnel, pour le cours nous le fournirons obligatoirement.

Page 29: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

V - Structures de contrôle page 29/73 Algorithmique-Programmation

V - Structures de contrôle

V.1 - Signalisation d’erreurLa façon de signaler les erreurs dépend des mécanismes disponibles dans le langage et de la façon dont des librairies utilisées ont été conçues. On trouve deux grandes façons de faire : les codes d'erreurs — valeurs rendues disponibles après une section de code et qui indiquent la détection ou non d'une erreur dans cete section — et les exceptions.

Les exceptions ont été citées à la section « Erreurs en Python » p11. Le langage lui-même ainsi que ses librairies lèvent (déclenchent) des exceptions lorsqu’ils détectent des problèmes. Un programme peut aussi détecter une condition d’erreur (donnée invalide, cas non prévu…) qu’il ne peut pas traiter et qui empêche l’exécution de se poursuivre normalement, et alors lever une exception.

Qand une exception est levée, l’exécution est alors déroutée vers le système de traitement spécifque mis en place dans le programme (nous ne verrons pas ce mécanisme de traitement en cours).

Exemple de levée d'une exception en algorithmique :

(Détection d’une erreur)erreur «Valeur compteur négatif»

En Python, on utilise l’instruction raise qui nécessite de préciser une classe d’erreurs en lui donnant éventuellement en argument un message explicatif pour l’utilisateur. Parmi les nombreuses classes d’erreurs, citons Exception (très générique), ValueError (valeur erronée), TypeError (type de donnée invalide).

Il est conseillé, juste avant de lever l’exception, de produire une trace pour l'utilisateur, par exemple avec un afchage29 :

# Détection d'une erreur.print("Dans xxx, le compteur ne doit pas être négatif:", iCompeur)raise ValueError("Compteur négatif")

V.2 - Bloc d’instructionsIls sont utilisés dans les instructions composées pour spécifer les séquences d’instructions liées à des structures particulières.

En algorithmique on décale le bloc d’instructions par rapport à la structure de contrôle afn de l’identi-fer visuellement, et on peut éventuellement placer des mots clés début/fn pour bien identifer le bloc.

En Python une instruction composée contient :

• la ligne de la structure de contrôle, terminée par un caractère :

• le bloc d’instructions associé, constitué de toutes les lignes suivantes30 qui sont indentées par rapport à la ligne de la structure de contrôle

• le bloc se termine quand l’indentation deviens égale ou plus faible que celle de la ligne de la structure de contrôle associée.

Il est possible d’imbriquer des instructions composées à l’intérieur des blocs d’instructions d’autres instructions composées.

29 On utilise généralement un mécanisme de « journalisation des événements ».30 En ignorant les lignes de commentaires.

Page 30: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

V - Structures de contrôle page 30/73 Algorithmique-Programmation

V.3 - Instruction conditionnelle siCete instruction permet de n’exécuter un bloc d’instructions que dans certains cas, lorsqu’une condition logique est vérifée. Si la condition n’est pas vérifée le bloc n’est pas exécuté et on passe directement aux instructions à la suite de l’instruction condition-nelle.

Syntaxe en algo :

…avantsi condition alors début_si instruction1 instruction2 fin_si…après

Syntaxe en Python avec le mot clé if :

#avantif condition: instruction1 instruction2#après

Un exemple en algorithmique :

reçu ← fauxnote ← saisie(moyenne élève)si note >= 10 alors début_si afficher «eleve reçu» reçu ← vrai fin_siafficher «évaluation terminée»

En Python :

bRecu = FalsefNote = float(input("Moyenne élève: "))if fNote >= 10: print("Élève reçu") bRecu = Trueprint("Évaluation terminée.")

Et son exécution, deux fois avec des saisies diférentes :

Moyenne élève: 12Élève reçuÉvaluation terminée.Moyenne élève: 8.3Évaluation terminée.

Condition simpleSi la condition logique est contenue dans une variable booléenne préalablement calculée, elle peut s'ex-primer simplement avec cete variable :

if bValide == True: ⇔ if bValide:

if bValide == False: ⇔ if not bValide:

Page 31: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

V - Structures de contrôle page 31/73 Algorithmique-Programmation

V.3.a - Alternative sinonCete forme de l’instruction conditionnelle « si » permet de spé-cifer un second bloc d’instructions qui est exécuté lorsque la condition n’est pas vérifée. Après l’exécution d’un des deux blocs, on passe aux instructions à la suite de l’instruction condi-tionnelle.

Syntaxe en algo :

…avantsi condition alors début_si instruction1 instruction2 fin_sisinon début_sinon instructionA instructionB fin_sinon…après

Syntaxe en Python avec le mot clé else :

#avantif condition: instruction1 instruction2else: instructionA instructionB#après

L’exemple étendu en algo :

note ← saisie(moyenne élève)si note >= 10 alors début_si afficher «eleve reçu» reçu ← vrai fin_sisinon début_sinon afficher «eleve recalé» recu ← faux fin_sinonafficher «évaluation terminée»

En Python :

fNote = float(input("Moyenne élève: "))if fNote >= 10: print("Élève reçu") bRecu = Trueelse: print("Élève recalé") bRecu = Falseprint("Évaluation terminée.")

Exécutions :

Moyenne élève: 12Élève reçuÉvaluation terminée.Moyenne élève: 8.5Élève recaléÉvaluation terminée.

Page 32: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

V - Structures de contrôle page 32/73 Algorithmique-Programmation

V.3.b - Alternatives multiplesIl est enfn possible de vérifer une baterie de tests afn d’exécuter le bloc correspondant à la première condition vérifée, en ayant éventuellement un bloc fnal au cas où aucune des conditions ne serait véri-fée.

Exemple en Python :

# Classification canadienne par tranche d'age:iAge = int(input("Age (ans): "))if iAge <= 14: sClassification = "enfant"elif iAge <= 24: sClassification = "adolescent"elif iAge <= 64: sClassification = "adulte"else: sClassification = "aîné"print(f"Classifié en {sClassification.title()}")

Et trois exécutions avec trois saisies diférentes :

Age (ans): 12Classifié en Enfant

Syntaxe en Python avec le mot clé elif :

#avantif condition1: instruction1 instruction2elif condition2: instructionA instructionBelif condition3: instructionα instructionβelse: instructionψ instructionω#après

Syntaxe en algo :

…avantsi condition 1 alors début_si instruction1 instruction2 fin_sisinonsi condition 2 alors début_sinonsi instructionA instructionB fin_sinonsisinonsi condition 3 alors début_sinonsi instructionα instructionβ fin_sinonsisinon début_sinon instructionψ instructionω fin_sinon…après

Page 33: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

V - Structures de contrôle page 33/73 Algorithmique-Programmation

Age (ans): 45Classifié en AdulteAge (ans): 90Classifié en Aîné

V.3.c - Imbrication de conditionsComme toutes les structures de contrôle, les instructions conditionnelles peuvent être imbriquées. Exemple en Python :

fNote = float(input("Moyenne élève: "))if fNote >= 10: print("Élève reçu") bRecu = True if fNote >= 16: # La condition imbriquée print("Avec mention")else: print("Élève recalé") bRecu = Falseprint("Évaluation terminée.")

Exécutions :

Moyenne élève: 4Élève recaléÉvaluation terminée.Moyenne élève: 12Élève reçuÉvaluation terminée.Moyenne élève: 18Élève reçuAvec mentionÉvaluation terminée.

V.3.d - Choix multipleCertains langages de programmation ofrent des instructions spécifques31 permetant de tester une variable par rapport à plusieurs valeurs possibles (ou à des modèles). En algorithmique comme en Python, nous utiliserons des séries de tests d’alternatives multiples avec chacune de ces valeurs pos-sibles (cf. p32).

V.4 - Instruction de répétition tant queOu boucle tant que, elle permet d’itérer plusieurs fois dans le même bloc de code (le re-exécuter) tant qu’une condition reste vraie.

Cela apparaît bien dans l’organigramme, où on efectue un test sur la condition avant chaque exécution du bloc d’instructions.

On voit qu’il est possible de ne jamais exécuter le bloc d’ins-tructions, dans le cas où la condition est fausse dès le début.

On voit aussi qu’il est possible que l’exécution ne ressorte jamais de la boucle, dans le cas où la condition reste vrai malgré l’exécution du bloc d’instructions. On parle de boucle sans fn. Cela peut être volontaire (et dans ce cas voir la section « Rupture de boucle :::: stopper » p36), ou bien involontaire et pour l’éviter il faut s’as-surer qu’une des variables de l’expression de la condition est bien systématiquement modifée dans le bloc d’instructions et arrive à une valeur permetant de stopper la boucle.

Enfn, il est important d’initialiser les variables qui vont servir pour le contrôle de la boucle ou pour des calculs d’accumulation avant le début de la boucle (avant l’évaluation de la condition).

31 Souvent nommées switch, case, ou encore match.

Page 34: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

V - Structures de contrôle page 34/73 Algorithmique-Programmation

Syntaxe en algorithmique :

…avanttant que condition faire début_tantque instruction1 instruction2 fin_tantque…après

Syntaxe en Python avec le mot clé while :

#avantwhile condition: instruction1 instruction2#après

Un premier exemple, en algorithmique, où on connaît le nombre d’itérations désirées :

(Table de multiplication de 0 à 10 par N)N ← 3cpt ← 0tant que cpt <= 10 faire début_tantque multiple ← N * cpt affiche(cpt × N = multiple) cpt = cpt + 1 fin_tantqueafficher «évaluation terminée»

En Python :

# Table de multiplication de 0 à 10 par NN = 3 iCpt = 0while iCpt <= 10: iMultiple = N * iCpt print(f"{iCpt} × {N} = {iMultiple}") iCpt = iCpt + 1print("Évaluation terminée.")

Et son exécution :

0 × 3 = 01 × 3 = 32 × 3 = 63 × 3 = 94 × 3 = 125 × 3 = 156 × 3 = 187 × 3 = 218 × 3 = 249 × 3 = 2710 × 3 = 30Évaluation terminée.

Un second exemple, en Python, où on ne sait pas a priori combien de fois on va exécuter le bloc d’ins-tructions de la boucle (c’est d’ailleurs ce que l’on veut compter) :

# Combien de fois faut-il vider la moitié en partant d'un litre pour arriver à la goutte ?POIDS_GOUTTE = 34E-3 # Poids moyen d'une goutte: 34 mgPOIDS_LITRE = 1E3 # Poids d'un litre d'eau: 1 kg

print("Pour arriver d'un litre en dessous d'une goutte…")fPoids = POIDS_LITRE # Masse de départ du volume d'eauiNbFois = 0 # Comptage du nb de passages dans la bouclewhile fPoids > POIDS_GOUTTE: fPoids = fPoids / 2 # On en vide la moitié iNbFois = iNbFois + 1 # Un passage de plus dans la boucleprint(f"…il faut prendre la moitié {iNbFois} fois.")

Page 35: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

V - Structures de contrôle page 35/73 Algorithmique-Programmation

Pour arriver d'un litre en dessous d'une goutte……il faut prendre la moitié 15 fois.

Enfn un troisième exemple en Python, d’une boucle sans fn :

iCpt = 0while iCpt >= 0: # Cette condition sera toujours vraie… iCpt = iCpt + 1 print(f"J'en suis à {iCpt}")

Et l’exécution :

J'en suis à 1J'en suis à 2J'en suis à 3J'en suis à 4… (on sort par +C dans une console, par ++K ou par un clic sur dans Pyzo)

Note : Python ne propose pas d’autre instruction de boucle conditionnelle, mais certains langages per-metent d’exprimer des structures de contrôle « faire … tant que condition » (« do … while »), ou encore « répéter … jusqu’à condition » (« repeat … until »).

Il existe deux instructions, présentées ci-après, permetant de casser la logique d’une instruction de répétition. Elles sont utiles et pratiques dans certains cas, mais il faut faire bien ressortir leurs usages dans le code (commentaires…), car elles ne sont pas directement identifables avec l’indentation.

V.4.a - Raccourci de boucle : continuerUtilisable uniquement dans le cadre d’une boucle, cete instruc-tion permet de court-circuiter l’exécution du reste du bloc d’instructions de la boucle et de reprendre directement l’exécu-tion à l’évaluation de la condition en début de boucle32. Cela permet d’écarter simplement des cas inintéressants lors d’un traitement itératif.

En algorithmique on insère une instruction continuer tantque.

En Python on utilise le mot clé continue.

Un exemple où on veut calculer la somme, le produit et la somme des inverses pour les nombres entiers de 1 à MAX en excluant les multiples de 5.

Exemple en Python :

MAX = 22iVal = 0iSom = 0 # Penser à initialiser avant la boucleiProd = 1.0 # idemfSomInv = 0 # idemwhile iVal < MAX: iVal = iVal + 1 if iVal % 5 == 0: # Divisible par 5 continue # on ignore le cas --------------------> reprise de boucle iSom = iSom + iVal iProd = iProd * iVal fSomInv = fSomInv + 1 / iValprint(f"De 1 à {iVal} sans les multiples de 5, somme {iSom}, produit {iProd}, " f"somme inverses {fSomInv}")

Exécution :

De 1 à 22 sans les multiples de 5, somme 203, produit 74933381851840512, somme inverses 3.274146583550608

Note : en cas de boucles imbriquées, le continue agit par rapport à la boucle de niveau la plus proche.

32 Atention à assurer qu’il y a bien eu des évolutions dans les variables qui contrôlent la condition de la boucle.

Page 36: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

V - Structures de contrôle page 36/73 Algorithmique-Programmation

Atention, pour éviter une boucle sans fn, à s’assurer que, malgré l’instruction de continuer, on a bien une modifcation sur les variables liées à la condition de la boucle.

V.4.b - Rupture de boucle : stopperUtilisable uniquement dans le cadre d’une boucle, cete instruc-tion permet de sortir du bloc d’instructions de la boucle, pour reprendre l’exécution après l’instruction de boucle.

Elle est souvent utilisée lorsqu’on détecte dans le bloc d’ins-tructions d’une boucle qu’un objectif a été ateint et qu’on ne veut ni continuer le bloc ni ré-évaluer l’expression de condition de boucle. Utilisé aussi pour déporter dans le bloc d’instruc-tions certaines expressions compliquées de condition de boucle qui nécessitent des calculs sur plusieurs lignes. Utilisé parfois pour arrêter une boucle lorsqu’une erreur est détectée.

En algorithmique on insère une instruction stopper tantque.

En Python on utilise le mot clé break.

Exemple en Python :

# Trouver le n à partir duquel la somme des i 1…n deviens supérieur ou égal à 100MAX = 100iVal = 1while True: # Condition de boucle sans fin… l'arrêt est géré ailleurs # Calcul de la somme pour iVal iSom = 0 iCalc = 1 while iCalc <= iVal: # Ho, une boucle inmbriquée iSom = iSom + iCalc iCalc = iCalc + 1 # Test à partir de cette valeur calculée if iSom >= 100: # Résultat trouvé break # --------------------------------------> sortie de boucle iVal = iVal + 1print(f"La somme 1…{iVal} est arrivée à {iSom}")

Exécution :

La somme 1…14 est arrivée à 105

Note : en cas de boucles imbriquées, le break agit par rapport à la boucle de niveau la plus proche, si on veut sortir de plusieurs niveaux de boucles il faut positionner une variable et l’utiliser pour sortir des boucles les plus éloignées.

Page 37: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VI - Fonctions page 37/73 Algorithmique-Programmation

VI - Fonctions

En plus des alternatives conditionnelles et des boucles, on veut aussi pouvoir réutiliser à diférents endroits dans le programme des blocs de séquences d’instructions sans avoir à dupliquer leur code, pouvoir défnir des sous-programmes qui efectuent des taches particulières correspondant à des sous-parties de l’algorithme et ensuite les appeler simplement33.

On a déjà vu des fonctions standards Python (print(), input(), abs(), len()… ainsi que les fonctions de calcul du module math) et la façon de les appeler simplement en leur fournissant des valeurs de travail comme arguments entre parenthèses.

VI.1 - VocabulaireLes fonctions défnissent une interface (ou “signature”) :

• pour quels paramètres elles atendent qu’on leur fournisse des arguments (combien, de quels types, dans quel ordre/sous quel nom, pour quel usage),

• quelles valeurs de retour elles vont produire (s’il y en a),

• quels autres efets collatéraux ou efets de bord (s’il y en a).

À l’utilisation on ne sait pas comment elles calculent leurs valeurs de retour et produisent leurs efets collatéraux. On a juste, grâce à la documentation et à la syntaxe de la déclaration, une idée de ce qu’elles font mais sans savoir comment elles le font.

Le comment est ce qu’on appelle l’implémentation, il peut éventuellement changer, tant que l’inter-face n’est pas modifée c’est transparent pour les utilisateurs de la fonction.

On distingue la défnition d’une fonction, faite une fois pour toutes (où est codé l’implémentation de l’algorithme chargé du sous-problème que résout la fonction), de son utilisation à divers endroits dans le programme (les « appels » à la fonction).

L’implémentation se doit d’être générique, c’est une partie d’algorithme qui doit s’adapter aux don-nées à traiter34. Pour cela, on distingue dans les fonctions35 :

• les paramètres, noms utilisés dans la défnition de la fonction pour recevoir les données à trai-ter (qu’on ne connaît pas encore) et qui sont utilisés dans le bloc de code de la fonction,

• les arguments, valeurs transmises à la fonction pour une utilisation de celle-ci et associés aux paramètres pour cete exécution de la fonction.

VI.2 - DéfinitionLa défnition d’une fonction commence par une partie déclarative indiquant son nom (identifcateur) ainsi que les paramètres qu’elle atend en entrée et le type de résultat qu’elle doit retourner. On trouve ensuite un bloc d’instructions qui constitue le corps de la fonction, et qui sera efectivement exécuté chaque fois que la fonction sera appelée.

33 On verra dans le chapitre « Modules » comment créer des librairies réutilisables de fonctions.34 Pour autant que les données soient acceptables pour le traitement, en type et en domaine de validité ; une fonction peut prévoir de

vérifer cela par sécurité ou bien en laisser la responsabilité au code qui fait appel à elle.35 Dans la litérature on trouve paramètres formels pour les paramètres lors de la défnition de la fonction, et paramètres efectifs pour les

arguments transmis lors des appels à la fonction.

Page 38: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VI - Fonctions page 38/73 Algorithmique-Programmation

En algorithmique on pourra écrire une fonction val_absolue ainsi :

fonction val_absolue(x): début_fonction vabs ← x si x < 0 alors début_si vabs ← -x fin_si retourne vabs fin_fonction

En Python on déclare la même fonction ainsi, avec le mot clé def :

def val_absolue(x): vabs = x if x < 0: vabs = -x return vabs

• Paramètres entre les parenthèses, séparés par des virgules s’il y en a plusieurs.

• Bloc d’instructions, constituant le corps de la fonction, indenté par rapport à la déclaration def36.

• Instruction return utilisée dans le corps de la fonction37 pour indiquer une sortie de la fonc-tion en spécifant si nécessaire la valeur qui doit être retournée.

Attention retour de fonction : l’exécution d’une instruction return provoque la sortie immédiate de l’appel à la fonction, même s’il y a des instructions après dans le corps de celle-ci.On peut trouver plusieurs return dans une fonction — pour le cours on essaiera d’en avoir juste un à la fn de la fonction.

Le corps de la fonction peut commencer par une chaîne de caractères qui constitue la documentation de la fonction — on utilise une chaîne triple guillemets si la documentation fait plus d’une ligne.

Pour le cours, on utilisera la convention de nommage avec les préfxes de type et le sufxe _p pour les noms des paramètres.

L’exemple de val_absolue() en Python pour le cours :

def val_absolue(fx_p): """Retourne |x|.

Si x est positif, retourne sa valeur. Si x est négatif, retourne son opposé. """ fVabs = fx_p if fx_p < 0: fVabs = -fx_p return fVabs

Une fonction très simple, correspondant juste à une expression de calcul, peut être défnie en Python en deux lignes :

def a_sur_b(fa_p, fb_p): return fa_p / fb_p

Attention bugs : 1) Les paramètres reçoivent, lors de l’appel à la fonction, les données dont celle-ci a besoin pour travailler. Il est anormal dans une fonction de demander à l’utilisateur de saisir une valeur pour un paramètre.

36 La défnition d’une fonction est une instruction composée en Python.37 L’instruction return ne peut pas être utilisée hors du bloc d’instructions d’une fonction ou d’une méthode.

Page 39: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VI - Fonctions page 39/73 Algorithmique-Programmation

2) Sauf si demandé explicitement, une fonction ne fait pas d’afchage. Afcher la valeur résultat n’est pas équivalent à la retourner (même si le shell Python peut en donner l’impression).

VI.3 - Utilisation (appel)Une fois qu’elle a été défnie, une fonction peut être appelée autant de fois que nécessaire pour réaliser le traitement sur les données. À chaque appel le corps de la fonction est exécuté et travaille sur les valeurs d’arguments fournis pour les paramètres. Si la fonction retourne une valeur, celle-ci est utilisée dans l’expression où apparaît l’appel de la fonction, que ça soit une instruction d’afectation à une variable ou bien une expression de calcul.

Un exemple en algorithmique de programme faisant des appels à val_absolue() :

(définition de la fonction - voir précédemment)PT1 = 12,3PT2 = 34,2x ← saisie(abscisse)distPt1 = val_absolue(x - PT1)distPt2 = val_absolue(x - PT2)si distPt1 < distpPt2 alors début_si afficher «Plus proche du point 1» fin_sisinon début_sinon affiche «Plus proche du point 2» fin_sinonif val_absolue((PT1+PT2)/2 - x) < 1 alors début_si afficher «Très proche du milieu» fin_siafficher «Terminé»

En Python la défnition de la fonction doit être réalisée (dans l’ordre d’exécution des instructions) avant que les instructions qui y font appel ne soient exécutées. On défnit donc les fonctions au début du fchier source du programme, et on place à la fn le code dit programme principal (main) qui fait appel à ces fonctions.

L’appel à la fonction est réalisé grâce aux parenthèses après le nom de la fonction, entre lesquelles on place les arguments.

# Constantes.PT1 = 12.3PT2 = 34.2

# Définition de la fonctiondef val_absolue(fx_p): """Retourne |x|.

Si x est positif, retourne sa valeur. Si x est négatif, retourne son opposé. """ fVabs = fx_p if fx_p < 0: fVabs = -fx_p return fVabs

# Le programme principal, code utilisant la fonction, vient après sa définition.fx = float(input("Abscisse: "))fDispPt1 = val_absolue(fx - PT1) # Affectation directe du résultat à une variablefDispPt2 = val_absolue(fx - PT2)if fDispPt1 < fDispPt2: print("Plus proche du point 1")else: print("Plus proche du point 2")

Page 40: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VI - Fonctions page 40/73 Algorithmique-Programmation

if val_absolue((PT1 + PT2) / 2 - fx) < 1: # Utilisation dans une expression de condition print("Très proche du milieu")

Exécutions :

Abscisse: 12Plus proche du point 1Abscisse: 48.5Plus proche du point 2Abscisse: 23.5Plus proche du point 2Très proche du milieu

Lorsqu’on efectue l’exécution pas à pas avec Python Tutor, on voit clairement que chaque appel à la fonction val_absolue() entraîne la création temporaire d’un espace mémoire (frame) qui disparaît avec toutes les données lorsque la fonction retourne.

Ci-dessous les états mémoire durant le premier appel à val_absolue() (ligne d’afectation à fDispPt1) et durant les second appel à cete fonction (ligne suivante) - on a saisi 12 pour l’abscisse :

VI.3.a - Arguments d’appelIl doit y avoir un argument fourni pour chaque paramètre déclaré de la fonction. S’il y a plusieurs paramètres, les arguments doivent être placés dans le même ordre. Les arguments doivent être du type atendu pour les paramètres38.

En algorithmique on séparera les arguments avec , ou ; ou un des espaces (tant que l’on comprend).

En Python les arguments doivent être séparés par des virgules. Exemple :

def politesse(bGenreMasc, sNom): "Retourne la chaîne formule de politesse correspondante pour la personne." sRes = "Bonjour " if bGenreMasc: sRes = sRes + "Monsieur " else: sRes = sRes + "Madame " sRes = sRes + sNom return sRes

print(politesse(True, "Williams"))print(politesse(False, "Michèle"))

38 Python ne force pas cete vérifcation de type à l’appel de fonction, contrairement à de nombreux langages.

Page 41: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VI - Fonctions page 41/73 Algorithmique-Programmation

Exécution :

Bonjour Monsieur WilliamsBonjour Madame Michèle

Autre exemple en Python :

def secdeg(fa_p, fb_p, fc_p, fx_p): "Calcule la valeur de ax²+bx+c" return fa_p * fx_p ** 2 + fb_p * fx_p + fc_p

print("Calcul:", secdeg(0.5, -1, 3.2, 2))print("Calcul:", secdeg(1, 0, 1, 3))

Exécution :

Calcul: 3.2Calcul: 10

Une fonction, qui trouve ses données de travail ailleurs, peut ne pas prendre de paramètre (et donc ne pas nécessiter d’argument). Un exemple en Python :

# Imports de librairies outilsimport datetime # Librairie Python de fonctions sur les dates et heuresdef mois(): "Retourne le n° du mois courant à partir de la date du jour actuel." return datetime.date.today().month

VI.3.b - Appels entre fonctionsUne fonction peut en appeler une autre. Tant que les fonctions ne sont pas appelées, leur ordre de défnition n’a pas d’importance. Un exemple, où la fonction moy_inv_sin() appelle la fonction inv_sin(), celle-ci appelle à son tour la fonction standard sin() du module math, le tout n’étant exécuté que lorsque le programme principal déclenche les appels aux fonctions :

# Imports de librairies outilsfrom math import sin

# Définition des constantes et variables globales du programme # (il n'y en a pas dans cet exemple)

# Définition des fonctions (ordre de définition sans importance)def moy_inv_sin(fx1_p, fx2_p): "Retourne la moyenne des inverses des sinus de x1 et x2" return (inv_sin(fx1_p) + inv_sin(fx2_p)) / 2

def inv_sin(fx_p): "Retourne l'inverse du sinus de x." return 1 / sin(fx_p)

# Programme principalfx1 = float(input("Première valeur: "))fx2 = float(input("Seconde valeur: "))fRes = moy_inv_sin(fx1, fx2)print(f"Moyenne des inverses des sinus: {fRes}")

Exécution :

Première valeur: 8Seconde valeur: 2Moyenne des inverses des sinus: 1.0552531943473569

Page 42: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VI - Fonctions page 42/73 Algorithmique-Programmation

Le suivi de l’exécution dans Python Tutor permet de visualiser les espaces mémoires temporaires alloués lors des appels des fonctions moy_inv_sin() et inv_in() :

Appels récursifsOn est en présence de fonctions récursives lorsqu’une fonction s’appelle elle-même, ou encore qu’un enchaînement d’appels de fonctions entraîne le rappel de l’une d’elles39. Ceci est assimilable à une boucle, il y a le même risque de boucle sans fn ; il faut donc faire atention à ce qu’une condition dans le corps de la fonction permete de sortir de la récursivité.

Un exemple en Python (calcul de factorielle40) :

# Définition des fonctionsdef fact(ix_p): """Retourne x!

Si x>0 calcule x × (x-1)! Si x=0 utilise 1 """ if ix_p > 0: # Condition permettant l'arrêt de la récursivité iRes = ix_p * fact(ix_p - 1) # Appel récursif à fact else: iRes = 1 # Appel non récursif return iRes

# Programme principaliVal = int(input("Factorielle de: "))print("Le résultat est", fact(iVal))

Exécutions :

Factorielle de: 1Le résultat est 1Factorielle de: 4Le résultat est 24Factorielle de: 10Le résultat est 3628800

39 Ceci est particulièrement utilisé par les informaticiens pour le traitement de données organisées en arborescences.40 Voir https://fr.wikipedia.org/wiki/Factorielle

Page 43: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VI - Fonctions page 43/73 Algorithmique-Programmation

Factorielle de: 20Le résultat est 2432902008176640000

Note : en Python l’utilisation de fonctions récursives peut mener à une erreur avec exception RecursionError lorsque le nombre d’appels récursifs cumulés devient trop important (par exemple ici avec fact(5000)).

VI.4 - Variables, portée et durée de vieLa portée d’une variable défnit les endroits dans le code du programme où celle-ci est visible, c’est-à-dire qu’il est possible de l’utiliser dans une expression ou bien de la modifer.

La durée de vie d’une variable est le laps de temps d’exécution au cours duquel la variable est défnie en mémoire et associé à une valeur41. Avant ce moment, la variable n’existe pas en mémoire. Une fois ce temps passé, la variable est détruite et n’existe plus en mémoire.

Variable locale Variable globale

Défni où Dans la fonction Dans le programme principal

Visible dans la fonction Oui Oui

Visible hors de la fonction Non Oui

Durée de vie Temps d’un appel de la fonction Temps d’exécution du programme

Attention visibilité et masquage : une variable locale à une fonction portant le même nom qu’une variable globale masquera celle-ci et la rendra inaccessible à partir de cete fonction.

Au niveau portée et durée de vie, les paramètres sont assimilables aux variables locales — toutefois, les valeurs des arguments fournis à l’appel pour les paramètres peuvent être accessibles hors de la fonction via d’autres variables (défnies hors de la fonction).

On utilise parfois des variables globales pour avoir un efet mémoire entre deux appels de fonctions et ainsi palier la durée de vie limitée des variables locales.

Attention afectation d’une globale : En Python, si l’on veut exécuter une afectation sur une variable globale dans une fonction, il faut spécifer dans la fonction une directive global nom. Sinon Python va créer une variable locale homonyme qui masquera la variable globale mais avec des valeurs diférentes.

Pour le cours on distinguera les variables globales accédées par des fonctions avec le sufxe _g, afn de bien identifer leur utilisation dans les corps des fonctions (sauf pour les constantes) et comme on a déjà vu, on distingue les paramètres avec le sufxe _p.

Exemple en Python :

# Définition des constantes et variables globales du programmeMAXIMUM = 100 # Limite maximum pour la somme totaleiSomTot_g = 0 # Cumul des sommes calculées

41 En Python, à partir de la ligne d’instruction qui réalise la première afectation d’une valeur à la variable.

Page 44: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VI - Fonctions page 44/73 Algorithmique-Programmation

# Définition des fonctionsdef ajouter(iVal1_p, iVal2_p): "Retourne val1+val2, met à jour la somme globale." global iSomTot_g # Nécessaire pour pouvoir re-affecter la variable globale iRes = iVal1_p + iVal2_p iSomTot_g = iSomTot_g + iRes if iSomTot_g > MAXIMUM: # On ne permet pas de dépasser le maxi, bornage iSomTot_g = MAXIMUM return iRes

# Programme principalprint("Première somme:", ajouter(14, 34))print("Seconde somme:", ajouter(4, 12))print("Somme totale:", iSomTot_g)print("Troisième somme:", ajouter(21, 12))print("Somme totale:", iSomTot_g)print("Quatrième somme:", ajouter(54, 9))print("Somme totale:", iSomTot_g)

Exécution :

Première somme: 48Seconde somme: 16Somme totale: 64Troisième somme: 33Somme totale: 97Quatrième somme: 63Somme totale: 100

VI.5 - Valeurs de retourJusqu’à maintenant nous avons utilisé l’instruction return afn que l’appel à la fonction fasse retourner une seule valeur.

VI.5.a - Valeurs multiplesUne fonction peut calculer et retourner plusieurs valeurs. Pour le cours, on récupérera par afectation les valeurs dans autant de variables qu’il y a de valeurs retournées.

En algorithmique on place simplement les valeurs après l’instruction de retour :

fonction somprod(a, b) début_fonction retourne a+b, a×b fin_fonctions,p ← somprod(1,5 10)s,p ← somprod(4 3)

En Python il suft de lister les valeurs à retourner avec l’instruction return, séparées par des virgules (on peut éventuellement metre des parenthèses) :

def somprod(fa_p, fb_p): "Retourne a+b, a×b" return (fa_p + fb_p, fa_p * fb_p) s, p = somprod(1.5, 10)print("Premier appel:", s, p)s, p = somprod(4, 3)print("Premier appel:", s, p)

Exécution :

Premier appel: 11.5 15.0Premier appel: 7 12

Page 45: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VI - Fonctions page 45/73 Algorithmique-Programmation

VI.5.b - Aucune valeur : ProcéduresLes procédures sont des fonctions qui ne produisent pas de valeur de retour, mais ont des efets collatéraux. Par exemple la fonction d’afchage ne calcule pas un résultat à retourner, mais elle a un efet visible sur l’écran.

C’est une erreur de récupérer le résultat d’une procédure ou encore d’utiliser l’appel à une procédure dans le cadre d’une expression de calcul.

En algorithmique on remplace le terme fonction par le terme procédure, et on n'a pas d'instruction de retour.

procédure docutilisateur(nom) début_procédure afficher «Documentation pour» nom fin_procédure

En Python les procédures sont déclarées comme des fonctions, mais ne spécifent pas de valeur de retour (soit elles n’ont pas du tout d’instruction return, soit celle-ci est seule sans valeur à retourner). De telles fonctions retournent implicitement une valeur Python spéciale : None.

def doc_utilisateur(sNom): "Affichage documentation pour l'utilisateur" print("Documentation pour", sNom)

doc_utilisateur("Jérôme")doc_utilisateur("Yacine")

Exécution :

Documentation pour JérômeDocumentation pour Yacine

VI.6 - Efets de bordOn parle d’efet de bord pour toutes les modifcations efectuées par une fonction sur des données qui ont été défnies et sont manipulées hors de cete fonction.

Il vaut mieux les éviter (voir « Fonctions pures » ci-après), mais si ce n’est pas possible alors il est essentiel d’indiquer de tels efets dans les commentaires et documentations des fonctions.

Modifcation des globales

Les variables globales sont visibles dans les fonctions. Elles peuvent y être modifées directement — voir « Variables, portée et durée de vie » p43.

Modifcation des paramètres

Certains langages permetent de transmetre, via les paramètres, non seulement des valeurs, mais aussi des références (adresses en mémoire) pour ces valeurs, autorisant ainsi leur modifcation directe au sein des fonctions sans avoir à connaître les variables externes qui les contiennent.

En Python les valeurs de base (int, float, bool, str) sont protégées contre ces modifcations, car elles sont immuables — on évitera tout de même de modifer la valeur associée à un paramètre. Mais nous verrons dans le chapitre « Tableaux de données » qu’il peut être possible de modifer le contenu des tableaux passés en argument.

VI.6.a - Fonctions puresCe sont les fonctions dont le fonctionnement ne dépend que des valeurs fournies en paramètres42, et qui ne fournissent que des valeurs de retour sans efet collatéral (ni efet de bord, ni action sur l’en-vironnement d'exécution du programme comme un afchage par exemple). Typiquement les fonctions de calcul du module math, ou encore les méthodes des chaînes str, sont pures.

42 Et éventuellement aussi des constantes défnies globalement.

Page 46: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VI - Fonctions page 46/73 Algorithmique-Programmation

Autant que possible, il faut privilégier ce type de fonctions. Elles sont plus faciles à tester. Qand on les appelle on est sûr que la seule modifcation dans l’état du programme sera la valeur produite en retour. On peut les assimiler à des boîtes noires qui ne communiquent en entrée que par les para-mètres, et en sortie que par les valeurs de retour.

Page 47: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VII - Tableaux de données page 47/73 Algorithmique-Programmation

VII - Tableaux de données

On a utilisé jusqu’ici des données simples, nombres, booléens, chaînes. Dans les algorithmes on arrive très rapidement à avoir à traiter des collections de don-nées et à devoir les stocker dans des conteneurs.

Un conteneur courant est le tableau de données homogènes. Il conserve des données dans un ordre et permet d’y accéder par leur indice (il y a une valeur à chaque indice, pas de “trou”). Il autorise la présence de la même donnée à plu-sieurs endroits (indices).

Exemples : le tableau des planètes du système solaire ci-contre (sans inclure les planètes naines), ou encore le tableau des températures mensuelles moyenne à Paris en 2018 ci-dessous43

En Python on utilisera le type conteneur list44, en le limitant au stockage de données homogènes45. Par abus de langage et par habitude, on utilisera simplement list pour tableau. C’est un conteneur dyna-mique (on peut augmenter ou réduire le nombre d’éléments pendant l’exécution du programme).

Attention : On utilise en algo et en Python46 des indices de 0 à nombre d’éléments -1.

VII.1 - Déclaration de tableauEn algorithmique on utilise simplement des valeurs écrites entre [] et si besoin séparées par , ou ; ou espace (tant que l’on comprend — avec les nombres il vaut mieux avoir un séparateur).

vide = []planetes = [«saturne» «mars» «jupiter» «vénus» «mercure» «uranus» «terre» «neptune»]temp = [3,3 ; 4,2 ; 7,8 ; 10,8 ; 14,3 ; 17,5 ; 19,4 ; 19,1 ; 16,4 ; 11,6 ; 7,2 ; 4,2]

En Python la représentation litérale d’une list47 utilise aussi des [] ainsi que le séparateur , entre les éléments :

liVide = [] # Une liste ne contenant aucun élémentlsPlanetes = ["saturne", "mars", "jupiter", "vénus", "mercure", "uranus", "terre", "neptune"]lfTemp = [3.3, 4.2, 7.8, 10.8, 14.3, 17.5, 19.4, 19.1, 16.4, 11.6, 7.2, 4.2]

Notez que tant que le [ n'a pas été refermé avec un ], l’expression litérale d'une list peut s’étaler sur les lignes suivantes.

43 Source : https://www.infoclimat.fr/44 Le nom est litigieux par rapport à son utilisation habituelle dans les autres langages de programmation, où on utilise plutôt le terme

array, le terme list étant réservé à une autre organisation des données en mémoire.45 En Python une list permet de stocker n’importe quelle collection de données hétérogènes.46 Certains langages vont de 1 à N, ou sont encore plus souples.47 Il existe d’autres façons de construire un tableau list, que nous ne verrons pas ici.

Page 48: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VII - Tableaux de données page 48/73 Algorithmique-Programmation

Avec l’exécution dans Python Tutor, on peut visualiser les variables créées en mémoire :

VII.2 - Opérations sur les tableauxEn Python on retrouve pour les list les mêmes opérations qu’avec les chaînes de caractères. Concaté-nation de deux list ou encore répétition d’une list, ces deux opérations créant une nouvelle list. Nombre d’éléments dans une list avec la fonction len() :

>>> [1, 2, 3] + [4, 5, 6][1, 2, 3, 4, 5, 6]>>> [0] * 10[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]>>> [1, 2] * 3[1, 2, 1, 2, 1, 2]>>> len([8, 4, 2, 3, 1, 4, 7])7

Les comparaisons entre list se font élément par élément, comme pour les chaînes.

>>> [1, 2, 4] > [1, 2, 3, 4] # Arrivé à l'indice 2, 4>3 donc 1è liste > 2è liste,True # même si celle-ci est plus longue

VII.2.a - IndexationEn Python les opérations d’indexation sur les list fonctionnent comme pour les chaînes, permetant d’extraire un élément à un indice particulier, ou encore d’extraire une sous-liste entre deux indices (le dernier non compris).

>>> l = [8, 4, 2, 3, 1, 4, 7]>>> l[0]8>>> l[-1]7>>> l[1:3][4, 2]

Par contre, contrairement aux chaînes, les list étant mutables, il est possible de modifer directement la valeur d’un élément à un indice, simplement en réalisant une afectation de la variable à cet indice48 :

>>> l[2] = 5>>> l # list modifiée[8, 4, 5, 3, 1, 4, 7]

VII.2.b - Méthodes sur les tableauxNous présentons encore des méthodes, avec la même notation programmation objet qu’avec les chaînes l.nomméthode() (ici la list est associée à l).

Attention : contrairement aux chaînes, certaines méthodes des list modifent directement les données référencées par la variable sans passer par une ré-afectation.

On dispose des outils de recherche similaires à ceux des chaînes, mais travaillant sur les valeurs des éléments de la list :

>>> l = [ 8, 4, 2, 3, 1, 4, 7]>>> l.count(4)2>>> l.index(3)3

48 Il est aussi possible de modifer un sous-tableau (ou tranche) par une afectation, mais nous ne l’utiliserons pas.

Page 49: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VII - Tableaux de données page 49/73 Algorithmique-Programmation

>>> 9 in lFalse>>> 12 not in lTrue

Les list étant mutables et dynamiques, il est possible d’ajouter des éléments (la taille de la list est augmentée d’autant) :

>>> l = [8, 4, 2, 3, 1, 4, 7]>>> l.append(5) # Ajoute valeur 5 tout à la fin>>> l # list modifiée[8, 4, 2, 3, 1, 4, 7, 5]>>> l.insert(3, 5) # Insère valeur 5 à l'indice 3>>> l # list modifiée[8, 4, 2, 5, 3, 1, 4, 7, 5]>>> l.extend([1, 2, 3]) # Concatène les éléments d'une autre liste à la fin>>> l # list modifiée[8, 4, 2, 5, 3, 1, 4, 7, 5, 1, 2, 3]

On peut aussi retirer des éléments (la taille de la list est raccourcie d’autant) :

>>> l = [8, 4, 2, 3, 1, 4, 7]>>> l.remove(1) # Suppression du premier élément de valeur 1>>> l # list modifiée[8, 4, 2, 3, 4, 7]>>> l.pop() # Suppression du dernier élément, qui est retourné7 >>> l # list modifiée[8, 4, 2, 3, 4]>>> l.pop(1) # Suppression de l'élément d'index 1, qui est retourné4>>> l # list modifiée[8, 2, 3, 4]>>> del l[2] # Suppression de l'élément d'index 2>>> l[8, 2, 4] # list modifiée

Il est aussi possible de trier les éléments (homogènes et comparables) d’une list, ainsi que d’inverser l’ordre des éléments :

>>> l = [8, 4, 2, 3, 1, 4, 7]>>> l.sort() # Tri les éléments, modification>>> l[1, 2, 3, 4, 4, 7, 8]>>> l.reverse() # Inversion de l'ordre des éléments, modification>>> l[8, 7, 4, 4, 3, 2, 1]

VII.2.c - Duplication de tableauJusqu’ici nous avons utilisé des variables référençant des données immuables (int, float, bool, str), dont les valeurs ne pouvaient pas être modifées une fois en mémoire, sauf à exécuter de nouvelles ins-tructions d’afectation aux variables concernées. Pour les list l’aspect mutable a des conséquences.

En Python les variables ne sont que des étiquettes qui référencent des données, et l’instruction d’af-ectation d’une variable à une autre ne fait que créer une nouvelle étiquette pour la même donnée.

Ainsi, si on exécute les instructions :

liT1 = [0, 2, 4, 6, 8, 10]liT2 = liT1liT1.remove(2)liT2.extend([11, 12, 13])print(liT1)print(liT2)

[0, 4, 6, 8, 10, 11, 12, 13][0, 4, 6, 8, 10, 11, 12, 13]

On peut voir avec Python Tutor que les deux noms référencent les mêmes données en mémoire… Et que si on modife la valeur d’une des deux variables, ces modifcations seront communes aux deux variables car efectuées sur la même list.

Page 50: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VII - Tableaux de données page 50/73 Algorithmique-Programmation

Pour éviter cela, lorsqu’on veut pouvoir modifer une variable list sans avoir d’impact sur d’autres variables, il faut efectuer une copie, simplement avec l’opérateur d’extraction de sous-liste [:] (du début à la fn) :

liT1 = [0, 2, 4, 6, 8, 10]liT2 = liT1[:]liT1.remove(2)liT2.extend([11, 12, 13])print(liT1)print(liT2)

[0, 4, 6, 8, 10][0, 2, 4, 6, 8, 10, 11, 12, 13]

Attention : lorsque vous modifez des tableaux, à ne pas modifer des données dont vous auriez besoin par ailleurs (dans une autre variable).

L’opérateur Python is permet de tester si deux variables référencent la même list :

>>> liT1 = [0, 2, 4, 6, 8, 10]>>> liT2 = liT1 # Affectation directe>>> liT1 is liT2True # → même list>>> liT3 = liT1[:] # Affectation d'une copie>>> liT1 is liT3False # → des list différentes

VII.3 - Instruction de boucle sur tableauIl est tout à fait possible de gérer soi-même, dans une boucle “tant que”, la variation d’un indice pour parcourir les éléments d’une list :

lsVal = ["un", "deux", "trois", "quatre"]iIndice = 0 # Pour démarrer à l'indice du premièr élémentwhile iIndice < len(lsVal): # Pour s'arrêter quand a dépassé le dernier indice sNum = lsVal[iIndice] # Récupération de la valeur à l'indice voulu print(sNum.title()) # Utilisation de la valeur iIndice = iIndice + 1 # Évolution de l'indice pour passer à l'élément suivant

UnDeuxTroisQuatre

Mais, cela fait beaucoup d’instructions et de risques d’erreurs49. Lorsqu’on a à parcourir dans l’ordre tous les éléments d’un tableau, un outil plus simple est disponible.

VII.3.a - Boucle sur les valeursLa boucle pour permet d’itérer dans le même bloc de code en fxant à chaque passage une variable de boucle avec tour à tour chacune des valeurs d’un tableau.

L’augmentation ou la réduction du nombre d’éléments dans le tableau au cours de la boucle est interdit.

49 Dans certains langages vous n’aurez pas le choix, ça sera la façon de faire.

Page 51: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VII - Tableaux de données page 51/73 Algorithmique-Programmation

On voit qu’il est possible de ne jamais exécuter le bloc d’instructions, dans le cas où le tableau est vide.

L’instruction gérant la boucle à partir d’un tableau de dimension bornée, il n’est pas possible de faire une boucle “pour” sans fn.

Après la boucle, la variable de boucle reste afectée à la dernière valeur traitée.

Syntaxe en algorithmique, il faut fournir le tableau t à parcourir et la variable v qui sera afectée tour à tour à chacune des valeurs :

pour v dans t début_pour (traitement sur v) fin_pour

Syntaxe en Python, avec l’instruction de boucle for … in (reprise de l'exemple précédent) :

lsVal = ["un", "deux", "trois", "quatre"]for sNum in lsVal: # Pour chaque valeur des éléments de lsVal print(sNum.title()) # Utilisation de la valeur

UnDeuxTroisQuatre

La list à parcourir est lsVal, et la variable de boucle est sNum. Tous les éléments de lsVal sont traités, un par un, dans l’ordre où ils ont été stockés.

Notes : Cete forme de boucle est utilisable sur les chaînes de caractères, la variable de boucle est afectée à la valeur de chaque caractère, un par un.Il est possible de faire une telle boucle sur un sous-tableau, par exemple :for SNum in lsVal[1:-1]: …

Transformation d’un tableauUne opération courante est la création d’un nouveau tableau, rempli en réalisant une transformation sur chacun des éléments d’un tableau existant.

Exemple en Python pour convertir tous les éléments d’un type dans un autre :

lsVal = ["78", "12", "45", "5", "89"]liVal = [] # On commence avec la nouvelle list videfor sVal in lsVal: # Traite chaque élément de la list existante liVal.append(int(sVal)) # Rempli la nouvelle liste avec .append(transtypage)print(lsVal) # list de strprint(liVal) # list de int

['78', '12', '45', '5', '89'][78, 12, 45, 5, 89]

Exemple en Python pour appliquer une fonction de calcul sur chaque élément :

from math import sin, pi

# Définition fonctionsdef f(fVal): # La fonction de transformation d'une valeur return 1 / sin(fVal)

# Programme principal lfTab = [ 0.1, pi/4, 3*pi/4, 9*pi/10]lfSin1 = [] # On commence avec la nouvelle list videfor fv in lfTab: # Traite chaque élément fv de la list existante lfSin1.append(f(fv)) # Rempli la nouvelle liste avec .append(f(fv))print(lfTab) # valeurs d'origineprint(lfSin1) # valeurs correspondantes calculées

Page 52: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VII - Tableaux de données page 52/73 Algorithmique-Programmation

[0.1, 0.7853981633974483, 2.356194490192345, 2.827433388230814][10.016686131634776, 1.4142135623730951, 1.414213562373095, 3.236067977499789]

VII.3.b - Boucle sur les indicesSous la forme précédente de boucle for, on accède directement aux valeurs, par contre on ne connaît pas les indices de leurs positions.

On a besoin de pouvoir boucler sur les indices dans diférents cas de traitement :

• Parcours simultané de plusieurs listes.

• Nécessité de connaître la valeur et son indice pour les calculs.

• Besoin d’accéder aux éléments avant/après chaque valeur (par leur indice).

En algorithmique on pourra écrire simplement ;

pour i dans indices(tableau) début_pour v = tableau[i] (traitement nécessitant v et/ou i) fin_pour

En Python la fonction50 range(n) permet de générer des séquences d’entiers de 0 à n-1, et range(d,f) des séquences d’entiers de d à f non compris. On peut l’utiliser dans les boucles for comme séquences d’indices que va parcourir la variable de boucle.

Astuce : Pour avoir d’un coup les valeurs générées dynamiquement par range(), par exemple pour les afcher, il faut passer par list(range(n)).

Au lieu de faire une boucle sur les éléments du tableau on écrit une boucle sur les éléments de la séquence d’indices :

lsVal = ["un", "deux", "trois", "quatre"]for iIndice in range(len(lsVal)): # Le range est construit à partir de la taille du list print(iIndice, lsVal[iIndice].upper()) # Accès à la valeur par son indice

0 UN1 DEUX2 TROIS3 QUATRE

Ci-après trois exemples pour les cas d’usage énoncés.

Parcours simultané de plusieurs listes

# Imports de librairies outilsfrom math import sqrt

# Programme principallfX = [1, 3, 4, 5]lfY = [0.5, 0.7, 11,-3.1]lfZ = [-5, 0, 3.4, 12]assert len(lfX) == len(lfY) and len(lfY) == len(lfZ) # Sécurité, list de même longueur# Accès aux valeurs x/y/z corrélées au même indicefor iIndice in range(len(lfX)): fx = lfX[iIndice] fy = lfY[iIndice] fz = lfZ[iIndice] fDist = sqrt(fx**2 + fy**2 + fz**2) print(f"Distance point n°{iIndice+1}: {fDist}")

Distance point n°1: 5.123475382979799Distance point n°2: 3.0805843601498726Distance point n°3: 12.188519188154071Distance point n°4: 13.364505228402585

50 En Python c’est en fait un type particulier, qui peut prendre d’autres paramètres de construction pour contrôler les entiers de la séquence générée.

Page 53: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VII - Tableaux de données page 53/73 Algorithmique-Programmation

Accès valeur et indice pour les calculslsMois = ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"]# Connaissance du n° du mois grace à l'ordre (donc l'indice, avec un décalage de 1)for iIndice in range(len(lsMois)): sMois = lsMois[iIndice] print(f"{sMois.title():10}: {iIndice+1:02}")

Janvier : 01Février : 02Mars : 03Avril : 04Mai : 05Juin : 06Juillet : 07Août : 08Septembre : 09Octobre : 10Novembre : 11Décembre : 12

Accéder aux éléments avant/aprèsDans ce cas de fgure, il faut faire atention à la gestion des indices au début / à la fn, afn de ne pas sortir des indices du tableau.

# Recherche de l'écart max entre deux valeurs consécutivesliPos = [1, 3, 6, 7, 12, 14, 18, 21]iDMax = 0for iIndice in range(1, len(liPos)): # À partir de l'indice 1 iPrec = liPos[iIndice - 1] # Accès au précédent → indice-1 iCur = liPos[iIndice] # Accès au courant → indice iDist = iCur - iPrec if iDist > iDMax: iDMax = iDistprint(f"Distance max entre deux valeurs: {iDMax}")

Distance max entre deux valeurs: 5

Note : cet exemple pourrait être écrit avec une boucle sur range(len()-1), en extrayant la valeur cou-rante et la valeur suivante (indice+1).

VII.4 - Fonctions et tableauxIl est possible de transmettre un tableau comme paramètre d’une fonction, exemple en Python :

# Définition des fonctionsdef maximum(lfTab): "Retourne la valeur maximale du tableau" if len(lfTab)==0: raise ValueError("Pas de max dans un tableau vide") fMax = lfTab[0] # Besoin d'initialiser avec une valeur du tableau for fVal in lfTab: # On pourrait boucler sur lfTab[1:]… if fVal > fMax: fMax = fVal return fMax # Programme principalprint("Valeur maxi:", maximum([1.2, 4.3, 2.5, 8.9, 3.1, 5.0]))

Valeur maxi: 8.9

Il est aussi possible de retourner un tableau comme résultat d’une fonction — en général ça sera un nouveau tableau créé dans la fonction.

# Définition des fonctionsdef an_str(liTab): "Retourne la liste des années sous forme de texte 'annee XXXX'" lsTab = []

Page 54: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VII - Tableaux de données page 54/73 Algorithmique-Programmation

for iv in liTab: lsTab.append("annee " + str(iv)) return lsTab

# Programme principalliAns = [1910, 1932, 1985, 2000, 2019]lsAnnees = an_str(liAns)print(lsAnnees)

['annee 1910', 'annee 1932', 'annee 1985', 'annee 2000', 'annee 2019']

VII.4.a - Efet de bord sur paramètreOn a déjà vu qu’une fonction pouvait avoir un efet de bord en modifant une variable globale directe-ment dans son bloc d’instructions.

En Python, avec une list en paramètre, il peut aussi y avoir un efet de bord (volontaire ou non) direc-tement sur le paramètre car ce type de donnée est mutable.

Un efet de bord involontaire, où on veut écrire une fonction retournant les versions en majuscules d’une list de chaînes :

# Définition des fonctionsdef liste_majuscules(lsChaines): "Retourne liste des chaines mises en majuscules" for iIndice in range(len(lsChaines)): lsChaines[iIndice] = lsChaines[iIndice].upper() return lsChaines

# Programme principallsNoms = ["jean", "yacine", "frédéric", "maurice"]lsNomsMaj = liste_majuscules(lsNoms)print("En majuscules:", lsNomsMaj)print("Originale:", lsNoms)

En majuscules: ['JEAN', 'YACINE', 'FRÉDÉRIC', 'MAURICE']Originale: ['JEAN', 'YACINE', 'FRÉDÉRIC', 'MAURICE']

Au lieu de construire une nouvelle list, la fonction a modifé directement le contenu de la list passée en paramètre : elle a modifé l’original contenant les données fournies lors de l’appel.

Un efet de bord volontaire, où une fonction corrige une list existante de nombres afn qu’ils ne dépassent pas une valeur maximale.

# Définition des fonctionsdef borner(lfTab, fMaxi): "Ajuste les valeurs du tableau pour qu'elles ne dépassent pas le maxi" for iIndice in range(len(lfTab)): if lfTab[iIndice] > fMaxi: lfTab[iIndice] = fMaxi

# Programme principallfVals = [12, 5.78, 4.5, 23.8, 9.3, 17.2]print("Avant bornage:", lfVals)borner(lfVals, 10)print("Après bornage:", lfVals)

Avant bornage: [12, 5.78, 4.5, 23.8, 9.3, 17.2]Après bornage: [10, 5.78, 4.5, 10, 9.3, 10]

Conseils : éviter les efets de bord sur les paramètres dans les fonctions. S’il y en a il vaut mieux qu’il s’agisse de procédures (voir « Aucune valeur :::: Procédures » p45), où il est clair qu’il y a un efet de bord.

Page 55: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VII - Tableaux de données page 55/73 Algorithmique-Programmation

VII.5 - Tableaux à 2 dimensionsOn peut avoir besoin, algorithmiquement, de défnir et manipuler des tableaux à 2 dimensions. Par exemple un tableau de coordonnées dans l’espace, où chaque coordonnée est elle-même un tableau de 3 valeurs. Ou encore une matrice dans un traitement numérique.

Syntaxe en algorithmique, on note la deuxième dimension comme des sous-tableaux de la première, et on accède directement aux éléments avec deux indices consécutifs :

mat = [[ 0,5 ; 6,2 ; 3,4 ] [ 1,3 ; -4,3 ; 11,2 ] [ -1 ; 11,4 ; -4,2 ]]pour ligne dans indices(mat) début_pour pour colonne dans indices(mat[ligne]) début_pour affiche ligne, colonne, mat[ligne, colonne] fin_pour fin_pour

Syntaxe en Python, les éléments de la list de premier niveau sont eux-mêmes des list, et on accède aux valeurs élémentaires par deux opérations d’extraction via les indices :

fMat = [[ 0.5 , 6.2 , 3.4 ], [ 1.3 , -4.3 , 11.2 ], [ -1 , 11.4 , -4.2 ]]for iLig in range(len(fMat)): for iCol in range(len(fMat[iLig])): print(iLig, iCol, fMat[iLig][iCol])

Avec Python Tutor on visualise bien la double indexation nécessaire pour accéder aux valeurs.

0 0 0.50 1 6.20 2 3.41 0 1.31 1 -4.31 2 11.22 0 -12 1 11.42 2 -4.2

Si on désire stocker des couples de valeurs (x, y) pour des points, il faut choisir un mode de stockage : chaque couple de valeurs ensemble, ou bien chaque dimension x et y ensemble. La façon d’indicer ne sera pas la même.

# Premier indice n° du point, second indice x ou ylliPts1 = [[0,0], [1,4], [5,3], [7,8], [8,3], [10,4]]

# On peut parcourir les points par valeur…for liPt in lliPts1: print(liPt[0], liPt[1])#… ou par indexfor iIndPt in range(len(lliPts1)): print(lliPts1[iIndPt][0], lliPts1[iIndPt][1])

0 01 45 37 88 310 40 01 45 37 88 310 4

Page 56: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VII - Tableaux de données page 56/73 Algorithmique-Programmation

# Premier indice x ou y, second indice n° du pointlliPts2 = [[0, 1, 5, 7, 8, 10], [0, 4, 3, 8, 3, 4 ]]# Il faut parcourir par index d'une des dimensionsfor iIndPt in range(len(lliPts2[0])): print(lliPts2[0][iIndPt], lliPts2[1][iIndPt])

0 01 45 37 88 310 4

Duplication de tableaux 2D : En Python la simple duplication par [:] ne fonctionne pas — seul le premier niveau est recopié. On utilise une fonction outil dédiée qui recopie tous les niveaux :

from copy import deepcopyliVar2DCopie = deepcopy(liVar2DOriginale)

Page 57: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VIII - Fichiers page 57/73 Algorithmique-Programmation

VIII - Fichiers

Dans le cadre du cours nous nous nous limiterons aux “fchiers textes”, qui contiennent des données directement lisibles par un humain et éditables facilement avec des outils externes51.

Là où l’exécution d’un programme est éphémère, et ses données en mémoire perdues lorsqu’il se ter-mine, les fchiers permetent d’assurer la pérennité des données. C’est le moyen privilégié pour récu-pérer les informations à traiter en entrée, et pour sauvegarder le résultat du traitement en sortie.

VIII.1 - Ouverture/FermetureLes fchiers sont des séquences d’octets stockées sur le disque sous un nom (dans un répertoire) et leur accès passe par le système d’exploitation. Les langages fournissent des fonctions permetant de deman-der au système d’exploitation un accès à un fchier particulier pour réaliser des opérations dessus.

Pour la suite nous donnons directement les fonctions/méthodes Python, sans la représentation algorith-mique.

VIII.1.a - OuvertureLe programme demande un accès à un fchier avec la fonction standard open() qui accepte trois argu-ments chaînes, dans l’ordre :

• le nom du fchier pour l’identifer,

• le mode, ou spécifcation des opérations que l’on veut faire dessus,

• l’encodage52, ou indication sur la représentation numérique des caractères.

Elle retourne un “objet fchier” qui sera stocké dans une variable afn d’être utilisé pour les opérations suivantes, par exemple :

ficData = open("mesures.txt", "r", encoding="utf8")

Pour le nom du fchier, on utilise aussi souvent une variable chaîne (ou un paramètre chaîne) qui a été afectée auparavant avec le bon nom. Le nom doit être complet, avec l’extension (par exemple .txt — atention car sous Windows par défaut l’explorateur de fchiers masque les extensions de fchiers connues…).

Attention : il est possible d’indiquer dans le nom du fchier un chemin d’accès, absolu par rapport au disque, ou relatif par rapport au répertoire courant.Pour faire simple lors des TPs, il est demandé de stocker les fchiers que l’on traite dans le même répertoire que le fchier script Python qui contient le programme.Si vous rencontrez une erreur FileNotFoundError, c’est que vous avez mal spécifé le nom du fchier ou bien que celui-ci est dans un autre répertoire.

Pour le mode d’ouverture, on utilise un des modes courants :

• "r" (read) pour la lecture de textes dans un fchier existant,

• "w" (write) pour l’écriture de textes dans un nouveau fchier créé vide (le contenu pré-existant de ce fchier est perdu !),

51 Par exemple notepad ou notepad++ sous Windows, TextEdit ou TextMate sous MacOS, gedit ou kate sous Linux…52 Ce 3è argument est optionnel, il est obligatoire pour le cours et fortement recommandé de toutes façons.

Page 58: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VIII - Fichiers page 58/73 Algorithmique-Programmation

• "a" (append) pour l’écriture de textes ajoutés à la fn d’un fchier.

Pour la directive d’encodage, dans le cours on spécife systématiquement l’encodage standard utf8 (il en existe d’autres, mais c’est maintenant le plus courant pour les fchiers textes).

Encodage : Une séquence d’octets, dans un fchier53, n’est pas « une chaîne », c’est la représentation numérique d’une chaîne suivant un encodage ; sans connaissance de l’encodage on ne peut passer de la chaîne à sa représentation et vice-versa.

chaîne de caractères ⇒encodage⇒ séquence d’octetsséquence d’octets ⇒décodage⇒ chaîne de caractères

Une fois le fchier ouvert, le programme est prêt pour faire des opérations de lecture ou d’écriture (sui-vant le mode d’ouverture) en utilisant des méthodes de la variable fchier.

VIII.1.b - FermetureLorsqu’un programme n’en a plus besoin, il doit systématiquement fermer le fchier. Cela permet de s’assurer que les données sont bien écrites sur le disque54 et de libérer des ressources du système d’exploitation liées à la gestion du fchier.

On appelle la méthode close() sur la variable fchier :

ficData.close()

Une fois le fchier fermé, la variable fchier n’est plus utilisable pour le manipuler.

VIII.2 - LectureÀ l’ouverture en mode "r", la lecture démarre au début du fchier. Elle progresse dans le fchier au fur et à mesure que le programme demande à lire la partie de texte suivante. On peut lire le texte caractère par caractère, ligne par ligne, ou bien tout d’un seul bloc. Cela dépendra de l’usage que l’on a du fchier dans l’algorithme de traitement.

On dispose de la méthode read(1) pour lire un caractère ou read() pour lire tout le fchier, et la méthode readline() pour lire une ligne (jusqu’à et y-compris le caractère retour à la ligne). Ces méthodes retournent une chaîne contenant le texte lu. Lorsqu’il n’y a plus des données à lire ces méthodes retournent une chaîne vide (l’ensemble du fchier a déjà été lu, on est arrivé à la fn).

Exemple de lecture caractère par caractère et comptage des caractères e55 :

iCpt = 0fic1 = open("chanson-automne.txt", "r", encoding="utf8")s = fic1.read(1) # Démarrage de la lecturewhile s != "": # Boucle tant qu'on a pu lire un caractère via read(1) if s.lower() == "e": # Traitement… iCpt = iCpt + 1 s = fic1.read(1) # Avancement de la lecture au prochain caractère fic1.close()print(f"Lu {iCpt} caractères e")

Lu 36 caractères e

Exemple de lecture du fchier en un seul bloc pour tester ensuite la présence du mot “violon” :

fic1 = open("chanson-automne.txt", "r", encoding="utf8")s = fic1.read() # Lecture en un blocfic1.close()# On passe le texte en minuscules s = s.lower()if "violon" in s: print("Violon est présent")

53 Un fchier, une base de données, un document web… tout stockage hors du programme.54 Il existe la méthode flush() des fchiers qui permet de forcer l’écriture sans avoir à fermer le fchier.55 Le fchier de test contient le texte du poème Chanson d’automne de Paul Verlaine.

Page 59: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VIII - Fichiers page 59/73 Algorithmique-Programmation

else: print("Violon est absent")

Violon est présent

Dans le cas de lecture en un bloc, on peut refermer le fchier tout de suite après la lecture, car le texte correspondant a été chargé en mémoire. Atention toutefois à cete façon de lire, dans certains cas la mémoire de l’ordinateur ne permet pas de lire l’intégralité de très gros fchiers d’un coup.

Exemple de lecture ligne par ligne et de calcul du nombre moyen de caractères par ligne :

iCpt = 0 # Nombre de lignes non videsiSom = 0 # Nombre total de caractèresfic1 = open("chanson-automne.txt", "r", encoding="utf8")s = fic1.readline() # Démarrage de la lecturewhile s != "": # Boucle tant qu'on a pu lire une ligne via readline() s = s.strip() # Retire blancs début/fin, dont le retour à la ligne if s == "": # Passe les lignes vides entre strophes s = fic1.readline() # …penser à faire évoluer variable de boucle! continue iCpt = iCpt + 1 iSom = iSom + len(s) s = fic1.readline() # Avancement de la lecture à la prochaine lignefic1.close()print(f"En moyenne {iSom/iCpt:.02f} caractères par ligne, pour {iCpt} lignes")

En moyenne 13.72 caractères par ligne, pour 18 lignes

VIII.2.a - Lecture de nombresOn entend ici la lecture de la représentation de nombres dans un fchier texte. Il faut séparer les valeurs — on en a généralement plusieurs sur une ligne, avec un caractère de séparation — puis les convertir de leur représentation textuelle en valeurs numérique entier ou fotant suivant les besoins et enfn les utiliser.

Exemple de lecture d’un fchier de 2 colonnes de nombres fotants séparés par des espaces :

# Coordonnées x y2 3.424.2 7.895.3 8.117.1 6.23

On utilise une boucle sans fn avec break afn de n’avoir la lecture + pré-traitement qu’à un seul endroit, on stocke les valeurs lues sous leur forme fotante :

lfX = [] # Pour stocker sous forme flottante les valeurs lueslfY = []ficCoord = open("deuxcol.txt", "r", encoding="utf8")while True: # Partie de code de lecture dans le fichier s = ficCoord.readline() if s == "": # Détection de fin de fichier break # --------------------------------------> sortie de boucle # Ici le pré-traitement (nettoyage, passe lignes vides et lignes commentaires) s = s.strip() # Retire espaces/retour à la ligne au début/fin if s == "" or s.startswith('#'): continue # --------------------------------------> reprise de boucle

# Ici le traitement des données lues lsItems = s.split() # Découpage, adapter suivant le séparateur (ici espaces) if len(lsItems) < 2: # Sécurité, message plus clair pour l'utilisateur raise ValueError("Valeurs manquantes sur une ligne") lfX.append(float(lsItems[0])) # Dans cet exemple, on stocke séparément x et y lfY.append(float(lsItems[1]))ficCoord.close()print(lfX, lfY)

[2.0, 4.2, 5.3, 7.1] [3.42, 7.89, 8.11, 6.23]

Page 60: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VIII - Fichiers page 60/73 Algorithmique-Programmation

VIII.3 - ÉcritureÀ l’ouverture, l’écriture démarre soit au début d’un nouveau fchier vide (mode "w"), soit à la fn du fchier (mode "a") qu’il soit nouveau ou existant. On peut écrire du texte par blocs au choix du pro-gramme, en incluant des caractères retour à la ligne lorsque besoin.

On dispose de la méthode write() pour écrire une chaîne de caractères. Toutes les données à écrire devront être converties en texte. Il est possible de construire des chaînes par conversion individuelle des éléments puis concaténation (opérateur + ou méthode join() des chaînes), ou encore avec les f-string présentées dans « Formatage des valeurs » p27.

Exemple d’écriture de diverses valeurs dans un nouveau fchier :

ia = 52fx = 67.78ficRes = open("resultat.txt", "w", encoding="utf8") # Ouverture en création+écritureficRes.write("Un début de texte,") # Ici pas de retour à la ligneficRes.write(" suite sur la même ligne.\n") # Ici un retour à la ligneficRes.write(f"a={ia} x={fx}\n") # Formatage de valeurs numériquesficRes.write("""On peut écrire des textesmulti-lignessimplement.""")for iVal in [3, 2, 6, 7]: # Plusieurs valeurs à écrire sur la même ligne ficRes.write(f"{iVal} ")ficRes.write("\n") # Fin de cette ligneficRes.close()

Ce qui donne le contenu du fchier resultat.txt :

Un début de texte, suite sur la même ligne.a=52 x=67.78On peut écrire des textesmulti-lignessimplement.3 2 6 7

Exemple d’écriture à la suite de ce même fchier :

sLang = "Python"ficRes = open("resultat.txt", "a", encoding="utf8")ficRes.write("On ajoute du texte\n")ficRes.write("Autant que l'on veut\n")ficRes.write(f"avec {sLang}.\n")ficRes.close()

Le contenu du fchier a été enrichi :

Un début de texte, suite sur la même ligne.a=52 x=67.78On peut écrire des textesmulti-lignessimplement.3 2 6 7 On ajoute du texteAutant que l'on veutavec Python.

VIII.3.a - Écriture de nombresOn entend ici l’écriture de la représentation de nombres dans un fchier texte. Il faut parcourir les valeurs à écrire en les rassemblant par ligne, formater le texte de la ligne correspondante avec les nombres et séparateurs (sans oublier le caractère de retour à la ligne) puis l’écrire.

Exemple d’écriture d’un fchier de 2 colonnes de nombres fotants séparés par des espaces :

LlfPts = [[2.0, 3.42], [4.2, 7.89], [5.3, 8.11], [7.1, 6.23]]ficCoord = open("deuxcolbis.txt", "w", encoding="utf8")ficCoord.write("# Coordonnées x y\n") # On a ajouté une ligne d'en-têtefor lfPt in llfPts:

Page 61: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

VIII - Fichiers page 61/73 Algorithmique-Programmation

fx = lfPt[0] # Récupère séparément les valeurs pour les formater fy = lfPt[1] ficCoord.write(f"{fx:0.1f} {fy:0.2f}\n")ficCoord.close()

On obtient le fchier suivant :

# Coordonnées x y2.0 3.424.2 7.895.3 8.117.1 6.23

Page 62: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

IX - Modules page 62/73 Algorithmique-Programmation

IX - Modules

Pour développer de nouveaux algorithmes on se base généralement sur d’autres algorithmes déjà prêts, qui traitent une partie du problème et facilitent la solution. En programmation on utilise la notion de bibliothèque (library), fournissant des fonctions, des données, des classes (cf « Programmation Objet » p66).

En Python on utilise les termes de module et de package (rassemblement de modules). Un module est simplement un fchier script Python56 (extension .py) comme on en a déjà écrit tout au long du cours57. Chaque module défnit un espace de noms propre, qui contient tout ce que le module a défni comme variables globales, fonctions ou classes, ainsi que tout ce qu’il a importé — pour le instructions de ce module, tous ces noms sont directement accessibles.

Python fournit de nombreux modules standards (il est bateries included), que l’on peut importer et uti-liser pour ne pas avoir à réinventer la roue58.

Attention : Avec Pyzo, il est important de lancer l’exécution des scripts par le menu Exécuter → Démarrer le script (E), afn de s’assurer que tous les modules sont rechargés.

IX.1 - ImportNous avons déjà vu l’import de noms d’un module avec l’instruction from math import pi, sin. Cete instruction provoque le chargement du module math en mémoire, ainsi que son exécution afn qu’il mete en place tout ce qu’il doit défnir (variables globales du module, fonctions). Ensuite les noms indiqués après import (ici constante pi et fonction sin()) sont afectés dans notre programme et rendus directement utilisables.

Une syntaxe alternative est l’import direct d’un module, avec l’instruction import math. Une fois le module chargé, tout ce qu’il défnit est accessible dans notre programme en passant par son nom (math.pi, math.sin()).

Le nom du fchier chargé par Python lors de l’import est simplement le nom du module importé auquel est ajouté l’extension .py. Le nom du module importé (avant .py) doit respecter les règles de syntaxe des identifcateurs Python (p24).

Un exemple qui charge diférents modules et les utilise, avec les deux syntaxes :

# Imports de librairies outilsfrom math import pi, sinimport time

# Programme principalfAngle = 3 * pi / 4fCalc = sin(fAngle)print(f"Angle {fAngle} ==> sinus {fCalc}")fNbSec = time.time() # Nombre de secondes depuis 1/1/1970, en flottanttime.sleep(3.5) # Attente de 3,5 secondesprint(f"Temps écoulé: {time.time()-fNbSec}")

Exécution :

56 Python permet aussi d’avoir des modules écrits en langage C et compilés en binaire.57 S’il s’agit d’un module outil, une bibliothèque, alors il n’aura généralement pas de partie « programme principal », juste des défni-

tions de données et de fonctions.58 Pour les découvrir, voir la documentation ainsi que les nombreux exemples sur le web.

Page 63: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

IX - Modules page 63/73 Algorithmique-Programmation

Angle 2.356194490192345 ==> sinus 0.7071067811865476Temps écoulé: 3.5154366493225098

IX.1.a - EmplacementLors d’un import, Python recherche un fchier script Python correspondant dans une série de réper-toires sur le disque. Le premier fchier trouvé est chargé (si le module a déjà été chargé, il est directe-ment utilisé tel qu’il est en mémoire).

Pour les TPs : pour simplifer, tous les modules pour un TP doivent être placés dans le même répertoire, créé pour ce TP.

IX.2 - DéfinitionComme indiqué, un module est simplement un fchier script Python comme nous en avons déjà écrit. En voici un exemple, dans un fchier script nommé outils.py (le nom outils respecte les règles sur les identifcateurs Python!).

# Fichier: outils.py"""Documentation du module outils.

C'est juste un module de démo pour le cours, qui définit diverses globaleset fonctions.Auteur: Prof."""

# Imports de librairies outilsfrom math import sin, cos, pi

# Définition constantes et globalesANGLEMAX = 2 * piiCpt_g = 0

# Définition des fonctions.def sincos(fAlpha): "Retourne le produit sin(α) × cos(α)" return sin(fAlpha) * cos(fAlpha)

# Pas de programme principal

Si vous exécutez ce programme dans l’interpréteur Python, il ne se passe rien. Rien de visible. À l’exé-cution, les noms (variables globales et fonctions, noms importés) ont été défnis en mémoire et référencés dans l’espace de noms outils, par lequel on peut y accéder.

La visualisation dans Python Tutor nous montre les noms défnis : noms importés, variables globales, fonctions.

On peut le voir aussi dans le Workspace de Pyzo :

Page 64: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

IX - Modules page 64/73 Algorithmique-Programmation

IX.3 - UtilisationPour tester un module de ce genre, il faut l’utiliser. On fera simplement un autre module qui l’importe et qui contient un programme principal avec le code de test. Par exemple ici on crée un fchier module nommé outils_test.py.

Lancement exécution : Dans Pyzo il faut bien utiliser Démarrer le script (raccourci E) en étant sur le script de test (programme principal).

# Fichier: outils_test.py"""Test du module outils."""

import mathimport outilsfrom outils import sincos, ANGLEMAX

# Utilisation du moduleprint("Début des tests sur outils")print("Produits de sinus et cosinus:")for fAng in [0, 1, math.pi / 3, math.pi / 2, ANGLEMAX]: print(f"\t{fAng} --> {sincos(fAng)}")print("Tests sur les globales")print(" iCpt_g de outil:", outils.iCpt_g)print(" ... ajout de 1 ...")outils.iCpt_g = outils.iCpt_g + 1print(" iCpt_g de outil:", outils.iCpt_g)print("Fin des tests sur outils")

Exécution :

Début des tests sur outilsProduits de sinus et cosinus:

0 --> 0.01 --> 0.45464871341284091.0471975511965976 --> 0.43301270189221941.5707963267948966 --> 6.123233995736766e-176.283185307179586 --> -2.4492935982947064e-16

Tests sur les globales iCpt_g de outil: 0 ... ajout de 1 ... iCpt_g de outil: 1Fin des tests sur outils

Attention : En Python, si vous voulez modifer des variables globales d’un autre module, il faut utiliser la syntaxe alternative (import module) et passer par le nom du module (module.variable = valeur).Avec la première syntaxe (from module import variable), il existe deux variables globales homonymes, une dans chaque module (qui ont chacun leur propre espace de noms). La modifcation directe de la variable dans votre module (variable = valeur) ne changera pas la variable globale dans le module importé.

Page 65: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

IX - Modules page 65/73 Algorithmique-Programmation

On peut voir dans le Workspace Pyzo les noms qui ont été importés dans l’espace de noms du module outils_test (qui est ici le module principal, celui qui a été exécuté et a importé les autres) :

Si vous double-cliquez sur outils, vous pourrez voir les noms défnis dans l’espace de noms outils. Chaque module possède bien son espace de noms propre, dans lequel il défnit et importe ce dont il a besoin.

Une fois testées, les fonctions du module outils sont utilisables dans n’importe quel autre programme Python, en l’important comme on a fait dans outils_test.

Page 66: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

X - Programmation Objet page 66/73 Algorithmique-Programmation

X - Programmation Objet

La POO (Programmation Orientée Objet) permet de structurer les programmes autour des données. Elle a étendu la notion de structure de donnée, qui permet de regrouper diférentes informations liées59, en y associant les algorithmes de traitement qui peuvent leur être appliqués.

X.1 - VocabulaireJusque-là on a manipulé des variables contenant des données simples, ou bien des tableaux de données homogènes, et créé des fonctions pour ces manipulations.

L’encapsulation est le regroupement d’un ensemble de données associées, appelées attributs, ainsi que des fonctions liées, appelées méthodes. La défnition de familles de structures dédiées, appelées classes, est une des façons de concevoir l’encapsulation. Pour chaque jeu de données associées, défnissant logiquement une telle structure, on crée un objet60 de la classe, dans lequel seront stockées les données.

À partir d’un objet on pourra accéder à ses atributs ou encore appeler ses méthodes pour le manipuler.

La notation pointée consiste à utiliser un . après une variable contenant un objet, pour accéder à ses atributs (obj.attribut) ou faire des appels à ses méthodes (obj.méthode(args…)). Dans le cas de l’appel à une méthode, l’objet concerné est implicitement transmis à la méthode (en Python c’est le premier argument).

X.2 - Exemple completPlutôt que de le découper en morceaux, l’ensemble de l’exemple en Python est placé ici, les sections suivantes introduisant les diférents concepts et indiquant les syntaxes et usages en Python.

Pour l'exemple, on défnit une famille d’objets permetant de manipuler des pièces d’un jeu d’échecs (on a défni quelques constantes par commodité).

X.2.a - Définition de la classe# Définition des constantes# Catégories de pièces, valeurs consécutives de 0 à 5 (important)ROI,DAME,FOU,CAVALIER,TOUR,PION = 0,1,2,3,4,5# Noms des pièces dans l'ordre des catégoriesNOMS = ['roi', 'dame', 'fou', 'cavalier', 'tour', 'pion']# Symboles des pièces (noir/blanc) dans l'ordre des catégoriesSYMB_BLANC = " "♔♕♗♖♘♙SYMB_NOIR = " "♚♛♝♜♞♟# Nombre de cases par côté de l'échiquierCOTE = 8# Valeurs noir et blancNOIR = TrueBLANC = False

# Définition des classesclass Piece: """Informations sur une pièce de jeu d'échecs.

Attributs: iCat code de catégorie de la pièce 0…5 (→roi,dame,fou,tour, cavalier,pion) sNom nom de la pièce

59 Déjà présente depuis longtemps dans de nombreux langages.60 Les informaticiens utilisent couramment le terme instance.

Page 67: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

X - Programmation Objet page 67/73 Algorithmique-Programmation

sSymb caractère symbole de la pièce bNoire vrai s'il s'agit d'une pièce noire, faux si c'est une pièce blanche iCol position sur la colonne 0…7 (→ a…h) iLig position sur la ligne 0…7 (→ 1…8) """ # Suite de la définition de la classe, méthodes et attributs def case(self): "Retourne la case en 2 caractères (ex: e4)" # Utilise le fait que les caractères concernés ont des codes consécutifs return chr(ord('a')+self.iCol) + chr(ord('1')+self.iLig)

def __init__(self, iCat_p, bNoire_p, iCol_p, iLig_p): self.iCat = iCat_p self.sNom = NOMS[iCat_p] if bNoire: self.sSymb = SYMB_NOIR[iCat_p] else: self.sSymb = SYMB_BLANC[iCat_p] self.bNoire = bNoire_p self.iCol = iCol_p self.iLig = iLig_p

def __str__(self): "Retourne la chaîne de représentation (pour l'affichage par exemple)" if self.bNoire: sCoul = "noir" else: sCoul = "blanc" sRes = f"<{self.sSymb} {self.sNom.title()} {sCoul} en {self.case()}>" return sRes

def mouvements(self): """Retourne la liste des positions futures autorisées Retourne une liste contenant des listes d'entiers [colonne, ligne], chacune correspondant à un mouvement possible sans considérer les positions des autres pièces sur l'échéquier, mais en restant sur celui-ci. Retourne une liste vide si aucun mouvement n'est possible. """ # Cela dépend de la pièce. raise NotImplementedError("Doit être défini dans une sous-classe")

def menace(self, oAutre_p): """Retourne vrai si l'autre pièce est menacée par celle-ci """ liAutrePos = [oAutre_p.iCol, oAutre_p.iLig] # On teste simplement si la position de l'autre pièce est dans # les positions possibles de celle-ci. return liAutrePos in self.mouvements()

class Roi(Piece): """Spécialisation d'une pièce ayant le rôle de roi.

Attributs supplémentaires: sSurnom surnom donné à un roi """ def __init__(self, bNoire_p, iCol_p, iLig_p, sSurnom_p): # Important: appeler l'initialiseur de la classe parente super().__init__(ROI, bNoire_p, iCol_p, iLig_p) self.sSurnom = sSurnom_p

def __str__(self): # Ajoute le surnom du roi à l'affichage if self.bNoire: sCoul = "noir" else: sCoul = "blanc" sRes = f"<{self.sSymb} Roi {self.sSurnom} {sCoul} en {self.case()}>" return sRes

Page 68: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

X - Programmation Objet page 68/73 Algorithmique-Programmation

def mouvements(self): # Pour le roi, ±1 case dans chaque direction lliMvts = [] # On liste tous les cas possibles, et on ignore ceux hors échéquier # ainsi que la position courante. liCol = [self.iCol-1, self.iCol, self.iCol+1] liLig = [self.iLig-1, self.iLig, self.iLig+1] for iCol in liCol: if iCol<0 or iCol>=COTE: # Sortie échéquier continue # --------> reprise de boucle for iLig in liLig: if iLig<0 or iLig>=COTE: # Sortie échéquier continue # --------> reprise de boucle if iLig == self.iLig and iCol == self.iCol: # Case actuelle continue # --------> reprise de boucle # Ce cas nous intéresse position = [iCol, iLig] lliMvts.append(position) return lliMvts

# On devrait bien sûr définir aussi les classes suivantes:# class Dame(Piece):# class Fou(Piece):# class Cavalier(Piece):# class Tour(Piece):# class Pion(Piece):

X.2.b - Utilisation de la classeOn considère que ce code de programme principal est après la défnition de la classe (en situation réelle on défnirait des modules et on utiliserait des imports…).

# Création de trois objets pièces pour testercn1 = Piece(CAVALIER, NOIR, 1, 7)fb = Piece(FOU, BLANC, 5, 0)dn = Piece(DAME, NOIR, 3, 7)

# Affichage des variablesprint(cn1)print(fb)print(dn)

# Accès aux attributsprint(cn1.sNom, cn1.bNoire, cn1.sSymb, cn1.iCol, cn1.iLig)print(fb.sNom, fb.bNoire, fb.sSymb, fb.iCol, fb.iLig)print(dn.sNom, dn.bNoire, dn.sSymb, dn.iCol, dn.iLig)

# Déplacement cavalier noir en c6print("Déplacement cavalier noir…")cn1.iCol = 2cn1.iLig = 5print(cn1.sNom, cn1.bNoire, cn1.sSymb, cn1.iCol, cn1.iLig)

# Appel de méthodeprint(cn1.sSymb, "en", cn1.case())print(fb.sSymb, "en", fb.case ())print(dn.sSymb, "en", dn.case ())

# Utilisation de la sous-classerb = Roi(BLANC, 4, 0, "Charles")print("Créé", rb, "de classe", type(rb))print("Mouvements possibles de", rb, ':', rb.mouvements())print("Menace de", dn, "par", rb, ":", rb.menace(dn))

Page 69: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

X - Programmation Objet page 69/73 Algorithmique-Programmation

X.3 - Définition de classeEn Python on utilise l’instruction class (instruction composée défnissant une nouvelle classe).

Comme toute instruction composée, le bloc de défnition de la classe est indenté par rapport à la ligne contenant le mot clé class.

On a mis ici la documentation de la classe (optionnelle), ainsi qu’une méthode position(self).

self61 : en Python, le paramètre spécial self, est le premier paramètre des méthodes de la classe, qui reçoit en argument l’objet utilisé dans la notation pointée.C’est par self que, dans les méthodes, on manipule les atributs de l’objet ou que l’on appelle d’autres méthodes de l’objet.

X.3.a - Définition des atributsLe bloc d’instructions de la classe contient normalement la défnition d’une méthode spéciale __init__()62 chargée d’initialiser les attributs de chaque nouvel objet de la classe lorsqu’il est créé (les objets sont créés initialement vide). Elle récupère les valeurs nécessaires dans ses paramètres, et les utilise pour initialiser les atributs de l’objet via self avec la notation pointée.

X.3.b - Représentation pour l’afichageLa méthode spéciale __str__() est appelée par Python lorsqu’il y a besoin d’une représentation tex-tuelle de l’objet (c’est la défnition de la conversion en str). Elle est utilisée de façon transparente par print() pour obtenir le texte à afcher.

Elle construit et retourne la chaîne que nous désirons pour cet afchage (ici les : symbole, nom et cou-leur de la pièce, ainsi que sa position, le tout entre <>).

X.4 - Manipulation d’objetsUne fois une classe défnie, elle peut être utilisée pour créer de nouveaux objets et travailler avec.

X.4.a - CréationLe nom de la classe est utilisé comme une fonction chargée de créer un nouvel objet. On lui fournit comme arguments ceux atendus par la méthode d’initialisation (hormis pour le self).

Dans notre exemple de pièces de jeu d’échec, on crée plusieurs pièces et on demande ensuite leur afc-hage. Qand la méthode spéciale __str__ n’est pas défnie, l’afchage n’est pas très pratique, mais il nous montre que trois objets distincts (on a 3 adresses d’objets diférentes), de la même classe Piece, ont été créés :

<__main__.Piece object at 0x7f7d40027eb8><__main__.Piece object at 0x7f7d40027898><__main__.Piece object at 0x7f7d40027e10>

Lorsque la méthode __str__ est défnie, l’afchage est plus lisible :

< Cavalier noir en b8>♞< Fou blanc en f1>♗< Dame noir en d8>♛

X.4.b - AtributsLes atributs de l’objet sont manipulés avec la notation pointée appliquée à la variable qui référence l’objet. On peut ainsi accéder à leur valeur, mais aussi la modifer par afectation. On rappelle que chaque objet a son propre jeu d’atributs.

61 En Python ce nom est juste une convention. Dans d’autres langages on peut trouver this, ou me.62 Appelée souvent constructeur.

Page 70: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

X - Programmation Objet page 70/73 Algorithmique-Programmation

cavalier True 1 7♞fou False 5 0♗dame True 3 7♛Déplacement cavalier…cavalier True 2 5♞

Attention : en Python une faute de frappe dans le nom d’un atribut lors d’une afectation obj.attribut = valeur peut faire créer un nouvel atribut à l’objet désigné, avec ce nom erroné.

X.4.c - MéthodesLes méthodes de l’objet sont appelées avec la notation pointée et les parenthèses d’appel (avec des arguments si nécessaires). Elles peuvent être défnies et sont utilisables comme n’importe quelle fonc-tion Python.

en c6♞ en f1♗ en d8♛

X.5 - Sous-classesDans l’exemple la défnition de la méthode mouvements() de la classe Piece se contente de signaler une erreur NotImplementedError. En efet, chaque catégorie de pièce a ses propres déplacements autorisés. Ceci va nous permetre d'introduire l'héritage de classes et la redéfnition de méthode (overloading).

X.5.a - HéritageL’héritage nous permet de défnir une sous-famille de pièces, partageant des caractéristiques com-munes, mais pouvant avoir des caractéristiques particulières des comportements spécifques (des actions diférentes lorsqu’on appelle leurs méthodes).

On défnit une relation « est-un » entre une classe enfant63 et une classe parent64, par laquelle les objets de la classe enfant bénéfcieront des atributs et méthodes défnis dans la classe parent, et pour-ront y jouter les leurs.

En modélisation UML65 on représente la relation d’héritage entre classes ainsi :

En Python, pour indiquer l’héritage, on a défni la classe Roi en indiquant la classe parente Piece entre parenthèses66.

Dans la défnition de la méthode d’initialisation __init__() de la sous-classe Roi, on a adapté les para-mètres de façon à se passer de la catégorie, qui est implicite avec la classe, et à pouvoir ajouter un sur-nom. Le code de cete méthode commence par appeler la méthode hérité de la classe parente, via super().__init__(…) appelée avec les bons arguments, afn que celle-ci mete en place normalement les atributs. Il stocke ensuite le nouvel atribut de surnom spécifque aux rois.

Un objet de la classe Roi est créé en utilisant celle-ci comme une fonction et en lui fournissant les para-mètres nécessaires à l’initialisation.

63 Appelée aussi classe dérivée.64 Appelée aussi classe héritée.65 Unifed Modeling Language - voir http://www.uml.org/66 On peut hériter de plusieurs classes parentes. Mais tous les langages ne le permetent pas, et ce n’est pas conseillé.

Page 71: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

X - Programmation Objet page 71/73 Algorithmique-Programmation

Créé < Roi Charles blanc en e1> de classe <class '__main__.Roi'>♔

X.5.b - RedéfinitionAussi appelé spécialisation, cela consiste à redéfnir dans une sous-classe une méthode d’une classe parente afn de changer ce que font les objets de la sous-classe. Dans la méthode de la classe enfant il est toutefois possible d’appeler la méthode héritée de la classe parente si besoin67.

Dans un algorithme on pourra considérer des objets Piece de façon générique, et appeler les méthodes sans avoir à se préoccuper de la classe réelle de l’objet. Suivant s’il s’agit efectivement d’un Roi, d’une Dame… d’un Pion, les méthodes de la classe correspondante seront appelées68.

La méthode __str__() a été redéfnie de façon à pouvoir fournir le surnom du roi dans la représenta-tion sous forme de texte (utilisée lors des print()).

La méthode mouvements() a été redéfnie afn de s’adapter aux mouvements autorisés par le roi dans les jeux d’échecs. La méthode menace() est héritée et peut directement être utilisée avec le l’objet roi.

Mouvements possibles de < Roi Charles blanc en e1> : [[3, 0], [3, 1], [4, 1], [5, 0], [5, ♔1]]Menace de < Dame noir en d8> par < Roi Charles blanc en e1> : False♛ ♔

Note : La méthode mouvements() est défnie dans la classe parente afn de donner une documentation générique sur son usage. Mais dans cete classe son bloc de code lève systématiquement une exception NotImplementedError afn d’obliger à utiliser des sous-classes fournissant leur code de calcul des mou-vements — un objet de la classe Piece n’a pas de sens car ses déplacements possibles ne sont pas encore défnis.

67 En Python, via super().… comme vu avec __init__().68 En informatique on pale de dynamic dispatch.

Page 72: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

XI - Python pratique page 72/73 Algorithmique-Programmation

XI - Python pratique

Dans cete version du cours les éléments suivants n’ont pas été présentés afn de limiter les éléments de programmation à ce qui est nécessaire pour transcrire les algorithmes et les exécuter. Si vous avez à programmer en Python dans des cas réels, il est recommandé de compléter vos connaissance sur le lan-gage en vous formant sur ces éléments ; votre code gagnera en simplicité, en efcacité et en robustesse.

Erreurs

• Mécanismes de capture et de traitement des exceptions.

Nombres

• Expression litérale de nombres en base binaire, octale, hexadécimale.

• Conversion de chaîne en entier en spécifant la base.

• Expression de nombres complexes.

Booléens

• Conversion implicite à partir des autres types.

• Combinaison d’opérateurs de comparaison d’ordre.

Indexation

• Spécifcation du pas dans une tranche.

Afectation

• Détails sur l’afectation de plusieurs variables en une seule instruction avec la même valeur, encapsulation / décapsulation en tuples.

• Opérateur * dans les afectations.

• Instruction d’afectation augmentée avec des opérateurs.

• Afectation de tranches de tableau (slices) en partie gauche.

Fonctions standards

• Nombreuses fonctions fournies en standard pour faciliter les calculs : min, max, sum…

Instruction conditionnelle

• If ternaire qui fournit directement une valeur ou une autre suivant une alternative, utilisable dans une expression de calcul.

Instructions de boucle

• Clause else activée lorsqu’on sort normalement d'une boucle.

Tableaux (listes)

• Construction litérale avec list().

• Construction par expressions en compréhension (boucle implicite de construction).

• Fonctions tri et itérateur inverse.

• Boucle avec un pas diférent de 1.

• Autres conteneurs (tuple, dictionnaires, ensembles).

• Outils tiers dédiés aux calculs matriciels avec numpy.

Page 73: Algorithmique Programmation - LIMSIcours:... · 2. l’algorithmique va nous fournir des constructions pour exprimer la résolution du problème, 3. le programme doit permetre d’exprimer

XI - Python pratique page 73/73 Algorithmique-Programmation

Fonctions

• Nombre variable de paramètres.

• Appels avec paramètres nommés.

• Paramètres avec valeur par défaut.

• Fonction transmise comme paramètre efectif à une autre fonction (utilisée comme « objet de première classe »).

• Récupération en un seul ensemble du tuple de plusieurs valeurs retournées.

Fichiers

• Arborescence des fchiers sur le disque, chemins absolu et relatif.

• Méthodes de lecture/écriture alternatives.

• Boucle de lecture itérant directement sur un fchier.

• Fermeture automatique avec les blocs gardés with.

• Fichiers binaires.

Modules

• Renommage des noms importés avec as.

• Le PYTHONPATH où sont cherchés les modules.

• L’auto-test dans la condition sur __name__.

Programmation objet

• Redéfnition d’opérateurs.

• Méthodes et atributs de classe.

• Relations de composition vs relations d’agrégation.

• Accesseurs.