Apprendre Python

Free texts and images.
Jump to: navigation, search
Apprendre Python
written by Gérard Swinnen









1








À l’école des sorciers



Apprendre à programmer est une activité déjà très intéressante en elle-même : elle peut stimuler puissamment votre curiosité intellectuelle. Mais ce n’est pas tout. Acquérir cette compétence vous ouvre également la voie menant à la réalisation de projets tout à fait concrets (utiles ou ludiques), ce qui vous procurera certainement beaucoup de fierté et de grandes satisfactions.

Avant de nous lancer dans le vif du sujet, nous allons vous proposer ici quelques réflexions sur la nature de la programmation et le comportement parfois étrange de ceux qui la pratiquent, ainsi que l’explication de quelques concepts fondamentaux. Il n’est pas vraiment difficile d’apprendre à programmer, mais il faut de la méthode et une bonne dose de persévérance, car vous pourrez continuer à progresser sans cesse dans cette science : elle n’a aucune limite.



Boîtes noires et pensée magique

Une caractéristique remarquable de notre société moderne est que nous vivons de plus en plus entourés de nombreuses boîtes noires. Les scientifiques ont l’habitude de nommer ainsi les divers dispositifs technologiques que nous utilisons couramment, sans en connaître ni la structure ni le fonctionnement exacts. Tout le monde sait se servir d’un téléphone, par exemple, alors qu’il n’existe qu’un très petit nombre de techniciens hautement spécialisés qui soient capables d’en concevoir un nouveau modèle.

Des boîtes noires existent dans tous les domaines, et pour tout le monde. En général, cela ne nous affecte guère, car nous pouvons nous contenter d’une compréhension sommaire de leur mécanisme pour les utiliser sans état d’âme. Dans la vie courante, par exemple, la composition précise d’une pile électrique ne nous importe guère. Le simple fait de savoir qu’elle produit son électricité à partir d’une réaction chimique nous suffit pour admettre sans difficulté qu’elle sera épuisée après quelque temps d’utilisation, et qu’elle sera alors devenue un objet polluant qu’il ne faudra pas jeter n’importe où. Inutile donc d’en savoir davantage.

Il arrive cependant que certaines boîtes noires deviennent tellement complexes que nous n’arrivons plus à en avoir une compréhension suffisante pour les utiliser tout-à-fait correctement dans n’importe quelle circonstance. Nous pouvons alors être tentés de tenir à leur encontre des raisonnements qui se rattachent à la pensée magique, c’est-à-dire à une forme de pensée faisant appel à l’intervention de propriétés ou de pouvoirs surnaturels pour expliquer ce que notre raison n’arrive pas à comprendre. C’est ce qui se passe lorsqu’un magicien nous montre un tour de passe-passe, et que nous sommes enclins à croire qu’il possède un pouvoir particulier, tel un don de « double vue », ou à accepter l’existence de mécanismes paranormaux ( « fluide magnétique », etc.), tant que nous n’avons pas compris le truc utilisé.

Du fait de leur extraordinaire complexité, les ordinateurs constituent bien évidemment l’exemple type de la boîte noire. Même si vous avez l’impression d’avoir toujours vécu entouré de moniteurs vidéo et de claviers, il est fort probable que vous n’ayez qu’une idée très confuse de ce qui se passe réellement dans la machine, par exemple lorsque vous déplacez la souris, et qu’en conséquence de ce geste un petit dessin en forme de flèche se déplace docilement sur votre écran. Qu’est-ce qui se déplace, au juste ? Vous sentez-vous capable de l’expliquer en détail, sans oublier (entre autres) les capteurs, les ports d’interface, les mémoires, les portes et bascules logiques, les transistors, les bits, les octets, les interruptions processeur, les cristaux liquides de l’écran, la micro-programmation, les pixels, le codage des couleurs … ?

De nos jours, plus personne ne peut prétendre maîtriser absolument toutes les connaissances techniques et scientifiques mises en œuvre dans le fonctionnement d’un ordinateur. Lorsque nous utilisons ces machines, nous sommes donc forcément amenés à les traiter mentalement, en partie tout au moins, comme des objets magiques, sur lesquels nous sommes habilités à exercer un certain pouvoir, magique lui aussi.

Par exemple, nous comprenons tous très bien une instruction telle que : « déplacer la fenêtre d’application en la saisissant par sa barre de titre ». Dans le monde réel, nous savons parfaitement ce qu’il faut faire pour l’exécuter, à savoir manipuler un dispositif technique familier (souris, pavé tactile …) qui va transmettre des impulsions électriques à travers une machinerie d’une complexité prodigieuse, avec pour effet ultime la modification de l’état de transparence ou de luminosité d’une partie des pixels de l’écran. Mais dans notre esprit, il ne sera nullement question d’interactions physiques ni de circuiterie complexe. C’est un objet tout à fait virtuel qui sera activé (la flèche du curseur se déplaçant à l’écran), et qui agira tout à fait comme une baguette magique, pour faire obéir un objet tout aussi virtuel et magique (la fenêtre d’application). L’explication rationnelle de ce qui se passe effectivement dans la machine est donc tout à fait escamotée au profit d’un « raisonnement » figuré, qui nous rassure par sa simplicité, mais qui est bel et bien une illusion.

Si vous vous intéressez à la programmation des ordinateurs, sachez que vous serez constamment confronté à des formes diverses de cette « pensée magique », non seulement chez les autres (par exemple ceux qui vous demanderont de réaliser tel ou tel programme), mais surtout aussi dans vos propres représentations mentales. Vous devrez inlassablement démonter ces pseudo-raisonnements qui ne sont en fait que des spéculations, basées sur des interprétations figuratives simplifiées de la réalité, pour arriver à mettre en lumière (au moins en partie) leurs implications concrètes véritables.

Ce qui est un peu paradoxal, et qui justifie le titre de ce chapitre, c’est qu’en progressant dans cette compétence, vous allez acquérir de plus en plus de pouvoir sur la machine, et de ce fait vous allez vous-même devenir petit à petit aux yeux des autres, une sorte de magicien !

Bienvenue donc, comme le célèbre Harry Potter, à l’école des sorciers !

Magie blanche, magie noire

Nous n’avons bien évidemment aucune intention d’assimiler la programmation d’un ordinateur à une science occulte. Si nous vous accueillons ici comme un apprenti sorcier, c’est seulement pour attirer votre attention sur ce qu’implique cette image que vous donnerez probablement de vous-même (involontairement) à vos contemporains. Il peut être intéressant aussi d’emprunter quelques termes au vocabulaire de la magie pour illustrer plaisamment certaines pratiques.

La programmation est l’art d’apprendre à une machine comment elle pourra accomplir des tâches nouvelles, qu’elle n’avait jamais été capable d’effectuer auparavant. C’est par la programmation que vous pourrez acquérir le plus de contrôle, non seulement sur votre machine, mais aussi peut-être sur celles des autres, par l’intermédiaire des réseaux. D’une certaine façon, cette activité peut donc être assimilée à une forme particulière de magie. Elle donne effectivement à celui qui l’exerce un certain pouvoir, mystérieux pour le plus grand nombre, voire inquiétant quand on se rend compte qu’il peut être utilisé à des fins malhonnêtes.

Dans le monde de la programmation, on désigne par le terme de hackers les programmeurs chevronnés qui ont perfectionné les systèmes d’exploitation de type Unix et mis au point les techniques de communication qui sont à la base du développement extraordinaire de l’internet. Ce sont eux également qui continuent inlassablement à produire et à améliorer les logiciels libres, dits « open source ». Dans notre analogie, les hackers sont donc des maîtres-sorciers, qui pratiquent la magie blanche.

Mais il existe aussi un autre groupe de gens que les journalistes mal informés désignent erronément sous le nom de hackers alors qu’ils devraient les appeler plutôt des crackers). Ces personnes se prétendent hackers parce qu’ils veulent faire croire qu’ils sont très compétents, alors qu’en général ils ne le sont guère. Ils sont cependant très nuisibles, parce qu’ils utilisent leurs quelques connaissances pour rechercher les moindres failles des systèmes informatiques construits par d’autres, afin d’y effectuer toutes sortes d’opérations illicites : vol d’informations confidentielles, escroquerie, diffusion de spam, de virus, de propagande haineuse, de pornographie et de contrefaçons, destruction de sites web, etc. Ces sorciers dépravés s’adonnent bien sûr à une forme grave de magie noire.

Mais il y en a une autre.

Les vrais hackers cherchent à promouvoir dans leur domaine une certaine éthique, basée principalement sur l’émulation et le partage des connaissances[1] . La plupart d’entre eux sont des perfectionnistes, qui veillent non seulement à ce que leurs constructions logiques soient efficaces, mais aussi à ce qu’elles soient élégantes, avec une structure parfaitement lisible et documentée. Vous découvrirez rapidement qu’il est aisé de produire à la va-vite des programmes d’ordinateur qui fonctionnent, certes, mais qui sont obscurs et confus, indéchiffrables pour toute autre personne que leur auteur (et encore ! ). Cette forme de programmation abstruse et ingérable est souvent aussi qualifiée de « magie noire » par les hackers.



La démarche du programmeur

Comme le sorcier, le programmeur compétent semble doté d’un pouvoir étrange qui lui permet de transformer une machine en une autre, une machine à calculer en une machine à écrire ou à dessiner, par exemple, un peu à la manière d’un sorcier qui transformerait un prince charmant en grenouille, à l’aide de quelques incantations mystérieuses entrées au clavier. Comme le sorcier, il est capable de guérir une application apparemment malade, ou de jeter des sorts à d’autres, via l’internet.

Mais comment cela est-il possible ?

Cela peut paraître paradoxal, mais comme nous l’avons déjà fait remarquer plus haut, le vrai maître est en fait celui qui ne croit à aucune magie, aucun don, aucune intervention surnaturelle. Seule la froide, l’implacable, l’inconfortable logique est de mise.

Le mode de pensée d’un programmeur combine des constructions intellectuelles complexes, similaires à celles qu’accomplissent les mathématiciens, les ingénieurs et les scientifiques. Comme le mathématicien, il utilise des langages formels pour décrire des raisonnements (ou algorithmes). Comme l’ingénieur, il conçoit des dispositifs, il assemble des composants pour réaliser des mécanismes et il évalue leurs performances. Comme le scientifique, il observe le comportement de systèmes complexes, il crée des modèles, il teste des prédictions.

L’activité essentielle d’un programmeur consiste à résoudre des problèmes.

Il s’agit-là d’une compétence de haut niveau, qui implique des capacités et des connaissances diverses : être capable de (re)formuler un problème de plusieurs manières différentes, être capable d’imaginer des solutions innovantes et efficaces, être capable d’exprimer ces solutions de manière claire et complète. Comme nous l’avons déjà évoqué plus haut, il s’agira souvent de mettre en lumière les implications concrètes d’une représentation mentale « magique », simpliste ou trop abstraite.

La programmation d’un ordinateur consiste en effet à « expliquer » en détail à une machine ce qu’elle doit faire, en sachant d’emblée qu’elle ne peut pas véritablement « comprendre » un langage humain, mais seulement effectuer un traitement automatique sur des séquences de caractères. Il s’agit la plupart du temps de convertir un souhait exprimé à l’origine en termes « magiques », en un vrai raisonnement parfaitement structuré et élucidé dans ses moindres détails, que l’on appelle un algorithme. Considérons par exemple une suite de nombres fournis dans le désordre : 47, 19, 23, 15, 21, 36, 5, 12 … Comment devons-nous nous y prendre pour obtenir d’un ordinateur qu’il les remette dans l’ordre ?

Le souhait « magique » est de n’avoir à effectuer qu’un clic de souris sur un bouton, ou entrer une seule instruction au clavier, pour qu’automatiquement les nombres se mettent en place. Mais le travail du sorcier-programmeur est justement de créer cette « magie ». Pour y arriver, il devra décortiquer tout ce qu’implique pour nous une telle opération de tri (au fait, existe-t il une méthode unique pour cela, ou bien y en a-t -il plusieurs ? ), et en traduire toutes les étapes en une suite d’instructions simples, telles que par exemple : « comparer les deux premiers nombres, les échanger s’ils ne sont pas dans l’ordre souhaité, recommencer avec le deuxième et le troisième, etc., etc.,… ».

Si les instructions ainsi mises en lumière sont suffisamment simples, il pourra alors les encoder dans la machine en respectant de manière très stricte un ensemble de conventions fixées à l’avance, que l’on appelle un langage informatique. Pour « comprendre » celui-ci, la machine sera pourvue d’un mécanisme qui décode ces instructions en associant à chaque « mot » du langage une action précise. Ainsi seulement, la magie pourra s’accomplir.



Langage machine, langage de programmation

À strictement parler, un ordinateur n’est rien d’autre qu’une machine effectuant des opérations simples sur des séquences de signaux électriques, lesquels sont conditionnés de manière à ne pouvoir prendre que deux états seulement (par exemple un potentiel électrique maximum ou minimum). Ces séquences de signaux obéissent à une logique du type « tout ou rien » et peuvent donc être considérés conventionnellement comme des suites de nombres ne prenant jamais que les deux valeurs 0 et 1. Un système numérique ainsi limité à deux chiffres est appelé système binaire.

Sachez dès à présent que dans son fonctionnement interne, un ordinateur est totalement incapable de traiter autre chose que des nombres binaires. Toute information d’un autre type doit être convertie, ou codée, en format binaire. Cela est vrai non seulement pour les données que l’on souhaite traiter (les textes, les images, les sons, les nombres, etc.), mais aussi pour les programmes, c’est-à-dire les séquences d’instructions que l’on va fournir à la machine pour lui dire ce qu’elle doit faire avec ces données.

Le seul « langage » que l’ordinateur puisse véritablement « comprendre » est donc très éloigné de ce que nous utilisons nous-mêmes. C’est une longue suite de 1 et de 0 (les « bits » ) souvent traités par groupes de 8 (les « octets » ), 16, 32, ou même 64. Ce « langage machine » est évidemment presque incompréhensible pour nous. Pour « parler » à un ordinateur, il nous faudra utiliser des systèmes de traduction automatiques, capables de convertir en nombres binaires des suites de caractères formant des mots-clés (anglais en général) qui seront plus significatifs pour nous.

Ces systèmes de traduction automatique seront établis sur la base de toute une série de conventions, dont il existera évidemment de nombreuses variantes.

Le système de traduction proprement dit s’appellera interpréteur ou bien compilateur, suivant la méthode utilisée pour effectuer la traduction. On appellera langage de programmation un ensemble de mots-clés (choisis arbitrairement) associé à un ensemble de règles très précises indiquant comment on peut assembler ces mots pour former des « phrases » que l’interpréteur ou le compilateur puisse traduire en langage machine (binaire).

Suivant son niveau d’abstraction, on pourra dire d’un langage qu’il est « de bas niveau » (ex : assembleur) ou « de haut niveau » (ex : Pascal, Perl, Smalltalk, Scheme, Lisp…). Un langage de bas niveau est constitué d’instructions très élémentaires, très « proches de la machine ». Un langage de haut niveau comporte des instructions plus abstraites, plus « puissantes » (et donc plus « magiques » ). Cela signifie que chacune de ces instructions pourra être traduite par l’interpréteur ou le compilateur en un grand nombre d’instructions machine élémentaires.

Le langage que vous avez allez apprendre en premier est Python. Il s’agit d’un langage de haut niveau, dont la traduction en code binaire est complexe et prend donc toujours un certain temps. Cela pourrait paraître un inconvénient. En fait, les avantages que présentent les langages de haut niveau sont énormes : il est beaucoup plus facile d’écrire un programme dans un langage de haut niveau ; l’écriture du programme prend donc beaucoup moins de temps ; la probabilité d’y faire des fautes est nettement plus faible ; la maintenance c’est-à-dire l’apport de modifications ultérieures) et la recherche des erreurs (les « bugs » ) sont grandement facilitées. De plus, un programme écrit dans un langage de haut niveau sera souvent portable, c’est-à-dire que l’on pourra le faire fonctionner sans guère de modifications sur des machines ou des systèmes d’exploitation différents. Un programme écrit dans un langage de bas niveau ne peut jamais fonctionner que sur un seul type de machine : pour qu’une autre l’accepte, il faut le réécrire entièrement.

Dans ce que nous venons d’expliquer sommairement, vous aurez sans doute repéré au passage de nombreuses « boîtes noires » : interpréteur, système d’exploitation, langage, instructions machine, code binaire, etc. L’apprentissage de la programmation va vous permettre d’en en trouver quelques-unes. Restez cependant conscients que vous n’arriverez pas à les décortiquer toutes. De nombreux objets informatiques créés par d’autres resteront probablement « magiques » pour vous pendant longtemps (à commencer par le langage de programmation lui-même, par exemple). Vous devrez donc faire confiance à leurs auteurs, quitte à être déçus parfois en constatant que cette confiance n’est pas toujours méritée. Restez donc vigilants, apprenez à vérifier, à vous documenter sans cesse. Dans vos propres productions, soyez rigoureux et évitez à tout prix la « magie noire » (les programmes pleins d’astuces tarabiscotées que vous êtes seul à comprendre) : un hacker digne de confiance n’a rien à cacher.



Édition du code source — Interprétation

Le programme tel que nous l’écrivons dans un langage de programmation quelconque est à strictement parler un simple texte. Pour rédiger ce texte, on peut faire appel à toutes sortes de logiciels plus ou moins perfectionnés, à la condition qu’ils ne produisent que du texte brut, c’est-à-dire sans mise en page particulière ni aucun attribut de style (pas de spécification de police, donc, pas de gros titres, pas de gras, ni de souligné, ni d’italique, etc.)[2]

Le texte ainsi produit est ce que nous appellerons désormais un « code source ».

Comme nous l’avons déjà évoqué plus haut, le code source doit être traduit en une suite d’instructions binaires directement compréhensibles par la machine : le « code objet ». Dans le cas de Python, cette traduction est prise en charge par un interpréteur assisté d’un pré-compilateur. Cette technique hybride (également utilisée par le langage Java) vise à exploiter au maximum les avantages de l’interprétation et de la compilation, tout en minimisant leurs inconvénients respectifs.

Veuillez consulter un ouvrage d’informatique générale si vous voulez en savoir davantage sur ces deux techniques. Sachez simplement à ce sujet que vous pourrez réaliser des programmes extrêmement performants avec Python, même s’il est indiscutable qu’un langage strictement compilé tel que le C peut toujours faire mieux en termes de rapidité d’exécution.



Mise au point d’un programme — Recherche des erreurs (debug)

La programmation est une démarche très complexe, et comme c’est le cas dans toute activité humaine, on y commet de nombreuses erreurs. Pour des raisons anecdotiques, les erreurs de programmation s’appellent des « bugs » (ou « bogues », en Français)[3], et l’ensemble des techniques que l’on met en œuvre pour les détecter et les corriger s’appelle « debug » (ou « débogage »).

En fait, il peut exister dans un programme trois types d’erreurs assez différentes, et il convient que vous appreniez à bien les distinguer.


Erreurs de syntaxe

Python ne peut exécuter un programme que si sa syntaxe est parfaitement correcte. Dans le cas contraire, le processus s’arrête et vous obtenez un message d’erreur. Le terme syntaxe se réfère aux règles que les auteurs du langage ont établies pour la structure du programme.

Tout langage comporte sa syntaxe. Dans la langue française, par exemple, une phrase doit toujours commencer par une majuscule et se terminer par un point. ainsi cette phrase comporte deux erreurs de syntaxe

Dans les textes ordinaires, la présence de quelques petites fautes de syntaxe par-ci par-là n’a généralement pas d’importance. Il peut même arriver (en poésie, par exemple), que des fautes de syntaxe soient commises volontairement. Cela n’empêche pas que l’on puisse comprendre le texte.

Dans un programme d’ordinateur, par contre, la moindre erreur de syntaxe produit invariablement un arrêt de fonctionnement (un « plantage » ) ainsi que l’affichage d’un message d’erreur. Au cours des premières semaines de votre carrière de programmeur, vous passerez certainement pas mal de temps à rechercher vos erreurs de syntaxe. Avec de l’expérience, vous en commettrez beaucoup moins.

Gardez à l’esprit que les mots et les symboles utilisés n’ont aucune signification en eux-mêmes : ce ne sont que des suites de codes destinés à être convertis automatiquement en nombres binaires. Par conséquent, il vous faudra être très attentifs à respecter scrupuleusement la syntaxe du langage.

Finalement, souvenez-vous que tous les détails ont de l’importance. Il faudra en particulier faire très attention à la casse c’est-à-dire l’emploi des majuscules et des minuscules) et à la ponctuation. Toute erreur à ce niveau (même minime en apparence, tel l’oubli d’une virgule, par exemple) peut modifier considérablement la signification du code, et donc le déroulement du programme.

Il est heureux que vous fassiez vos débuts en programmation avec un langage interprété tel que Python. La recherche des erreurs y est facile et rapide. Avec les langages compilés (tel le C++), il vous faudrait recompiler l’intégralité du programme après chaque modification, aussi minime soit-elle.



Erreurs sémantiques

Le second type d’erreur est l’erreur sémantique ou erreur de logique. S’il existe une erreur de ce type dans un de vos programmes, celui-ci s’exécute parfaitement, en ce sens que vous n’obtenez aucun message d’erreur, mais le résultat n’est pas celui que vous attendiez : vous obtenez autre chose.

En réalité, le programme fait exactement ce que vous lui avez dit de faire. Le problème est que ce que vous lui avez dit de faire ne correspond pas à ce que vous vouliez qu’il fasse. La séquence d’instructions de votre programme ne correspond pas à l’objectif poursuivi. La sémantique (la logique) est incorrecte.

Rechercher des fautes de logique peut être une tâche ardue. C’est là que se révélera votre aptitude à démonter toute forme résiduelle de « pensée magique » dans vos raisonnements. Il vous faudra analyser patiemment ce qui sort de la machine et tâcher de vous représenter une par une les opérations qu’elle a effectuées, à la suite de chaque instruction.



Erreurs à l’exécution

Le troisième type d’erreur est l’erreur en cours d’exécution (Run-time error), qui apparaît seulement lorsque votre programme fonctionne déjà, mais que des circonstances particulières se présentent (par exemple, votre programme essaie de lire un fichier qui n’existe plus). Ces erreurs sont également appelées des exceptions, parce qu’elles indiquent généralement que quelque chose d’exceptionnel (et de malencontreux) s’est produit. Vous rencontrerez davantage ce type d’erreurs lorsque vous programmerez des projets de plus en plus volumineux, et vous apprendrez plus loin dans ce cours qu’il existe des techniques particulières pour les gérer.



Recherche des erreurs et expérimentation

L’une des compétences les plus importantes à acquérir au cours de votre apprentissage est celle qui consiste à déboguer efficacement un programme. Il s’agit d’une activité intellectuelle parfois énervante mais toujours très riche, dans laquelle il faut faire montre de beaucoup de perspicacité.

Ce travail ressemble par bien des aspects à une enquête policière. Vous examinez un ensemble de faits, et vous devez émettre des hypothèses explicatives pour reconstituer les processus et les événements qui ont logiquement entraîné les résultats que vous constatez.

Cette activité s’apparente aussi au travail expérimental en sciences. Vous vous faites une première idée de ce qui ne va pas, vous modifiez votre programme et vous essayez à nouveau. Vous avez émis une hypothèse, qui vous permet de prédire ce que devra donner la modification. Si la prédiction se vérifie, alors vous avez progressé d’un pas sur la voie d’un programme qui fonctionne. Si la prédiction se révèle fausse, alors il vous faut émettre une nouvelle hypothèse. Comme l’a bien dit Sherlock Holmes : « Lorsque vous avez éliminé l’impossible, ce qui reste, même si c’est improbable, doit être la vérité » (A. Conan Doyle, Le signe des quatre).

Pour certaines personnes, « programmer » et « déboguer » signifient exactement la même chose. Ce qu’elles veulent dire par là est que l’activité de programmation consiste en fait à modifier, à corriger sans cesse un même programme, jusqu’à ce qu’il se comporte finalement comme vous le vouliez. L’idée est que la construction d’un programme commence toujours par une ébauche qui fait déjà quelque chose (et qui est donc déjà déboguée), à laquelle on ajoute couche par couche de petites modifications, en corrigeant au fur et à mesure les erreurs, afin d’avoir de toute façon à chaque étape du processus un programme qui fonctionne.

Par exemple, vous savez que Linux est un système d’exploitation (et donc un gros logiciel) qui comporte des milliers de lignes de code. Au départ, cependant, cela a commencé par un petit programme simple que Linus Torvalds avait développé pour tester les particularités du processeur Intel 80386. D’après Larry Greenfield ( « The Linux user’s guide », beta version 1) : « L’un des premiers projets de Linus était un programme destiné à convertir une chaîne de caractères AAAA en BBBB. C’est cela qui plus tard finit par devenir Linux ! ».

Ce qui précède ne signifie pas que nous voulions vous pousser à programmer par approximations successives, à partir d’une vague idée. Lorsque vous démarrerez un projet de programmation d’une certaine importance, il faudra au contraire vous efforcer d’établir le mieux possible un cahier des charges détaillé, lequel s’appuiera sur un plan solidement construit pour l’application envisagée.

Diverses méthodes existent pour effectuer cette tâche d’analyse, mais leur étude sort du cadre de ces notes. Nous vous présenterons cependant plus loin (voir chapitre 15) quelques idées de base. 10 Chapitre 1 - À l’école des sorciers






2








Premiers pas



La programmation est donc l’art de commander à un ordinateur de faire exactement ce que vous voulez, et Python compte parmi les langages qu’il est capable de comprendre pour recevoir vos ordres. Nous allons essayer cela tout de suite avec des ordres très simples concernant des nombres, puisque ce sont les nombres qui constituent son matériau de prédilection. Nous allons lui fournir nos premières « instructions », et préciser au passage la définition de quelques termes essentiels du vocabulaire informatique, que vous rencontrerez constamment dans la suite de cet ouvrage.

Remarque préliminaire : Comme nous l’avons expliqué dans la préface (voir : Versions du langage, page 10), nous avons pris le parti d’utiliser dans ce cours la nouvelle version 3 de Python, laquelle a introduit quelques changements syntaxiques par rapport aux versions précédentes. Dans la mesure du possible, nous vous indiquerons ces différences dans le texte, afin que vous puissiez sans problème analyser ou utiliser d’anciens programmes écrits pour Python 1 ou 2.



Calculer avec Python

Python présente la particularité de pouvoir être utilisé de plusieurs manières différentes. Vous allez d’abord l’utiliser en mode interactif, c’est-à —dire d’une manière telle que vous pourrez dialoguer avec lui directement depuis le clavier. Cela vous permettra de découvrir très vite un grand nombre de fonctionnalités du langage. Dans un second temps, vous apprendrez comment créer vos premiers programmes (scripts) et les sauvegarder sur disque.

L’interpréteur peut être lancé directement depuis la ligne de commande (dans un « shell » Linux, ou bien dans une fenêtre DOS sous Windows) : il suffit d’y taper la commande python3 (en supposant que le logiciel lui-même ait été correctement installé, et qu’il s’agisse d’une des dernières versions de Python), ou python (si la version de Python installée sur votre ordinateur est antérieure à la version 3.0).

Si vous utilisez une interface graphique telle que Windows, Gnome, WindowMaker ou KDE, vous préférerez vraisemblablement travailler dans une « fenêtre de terminal », ou encore dans un environnement de travail spécialisé tel que IDLE. Voici par exemple ce qui apparaît dans une fenêtre de terminal Gnome (sous Ubuntu Linux)[4]

Figure 1

Avec IDLE sous Windows, votre environnement de travail ressemblera à celui-ci :

Figure 2

Les trois caractères « supérieur à » constituent le signal d’invite, ou prompt principal, lequel vous indique que Python est prêt à exécuter une commande.

Par exemple, vous pouvez tout de suite utiliser l’interpréteur comme une simple calculatrice de bureau. Veuillez donc vous-même tester les commandes ci-dessous (Prenez l’habitude d’utiliser votre cahier d’exercices pour noter les résultats qui apparaissent à l’écran) :

>>> 5+3
>>> 2–9 # les espaces sont optionnels
>>> 7 + 3 * 4 # la hiérarchie des opérations mathématiques
# est-elle respectée ?
>>> (7+3) * 4
>>> 20 / 3 # attention : ceci fonctionnerait différemment sous Python 2
>>> 20 // 3


Comme vous pouvez le constater, les opérateurs arithmétiques pour l’addition, la soustraction, la multiplication et la division sont respectivement +, ―, * et /. Les parenthèses ont la fonction attendue.

Sous Python 3, l’opérateur de division l’effectue une division réelle. Si vous souhaitez obtenir une division entière se’est-à-dire dont le résultat — tronqué — ne peut être qu’un entier), vous devez utiliser l’opérateur //. Veuillez bien noter que ceci est l’un des changements de syntaxe apportés à la version 3 de Python, par rapport aux versions précédentes. Si vous utilisez l’une de ces versions, sachez que l’opérateur l’y effectue par défaut une division entière, si on lui fournit des arguments qui sont eux-mêmes des entiers, et une division réelle, si au moins l’un des arguments est un réel. Cet ancien comportement de Python a été heureusement abandonné car il pouvait parfois conduire à des bugs difficilement repérables.


>>>20.5 / 3
>>>8, 7 / 5 # Erreur !


Veuillez remarquer au passage ce qui est la règle dans tous les langages de programmation, à savoir que les conventions mathématiques de base sont celles qui sont en vigueur dans les pays anglophones : le séparateur décimal y est donc toujours un point, et non une virgule comme chez nous. Notez aussi que dans le monde de l’informatique, les nombres réels sont souvent désignés comme des nombres « à virgule flottante » (floating point numbers).



Données et variables

Nous aurons l’occasion de détailler plus loin les différents types de données numériques. Mais avant cela, nous pouvons dès à présent aborder un concept de grande importance.

L’essentiel du travail effectué par un programme d’ordinateur consiste à manipuler des données. Ces données peuvent être très diverses (tout ce qui est numérisable, en fait[5], mais dans la mémoire de l’ordinateur elles se ramènent toujours en définitive à une suite finie de nombres binaires.

Pour pouvoir accéder aux données, le programme d’ordinateur (quel que soit le langage dans lequel il est écrit) fait abondamment usage d’un grand nombre de variables de différents types.

Une variable apparaît dans un langage de programmation sous un nom de variable à peu près quelconque (voir ci-après), mais pour l’ordinateur il s’agit d’une référence désignant une adresse mémoire, c’est-à-dire un emplacement précis dans la mémoire vive.

À cet emplacement est stockée une valeur bien déterminée. C’est la donnée proprement dite, qui est donc stockée sous la forme d’une suite de nombres binaires, mais qui n’est pas nécessairement un nombre aux yeux du langage de programmation utilisé. Cela peut être en fait à peu près n’importe quel « objet » susceptible d’être placé dans la mémoire d’un ordinateur, par exemple : un nombre entier, un nombre réel, un nombre complexe, un vecteur, une chaîne de caractères typographiques, un tableau, une fonction, etc.

Pour distinguer les uns des autres ces divers contenus possibles, le langage de programmation fait usage de différents types de variables (le type entier, le type réel, le type chaîne de caractères, le type liste, etc.). Nous allons expliquer tout cela dans les pages suivantes.



Noms de variables et mots réservés

Les noms de variables sont des noms que vous choisissez vous-même assez librement. Efforcez-vous cependant de bien les choisir : de préférence assez courts, mais aussi explicites que possible, de manière à exprimer clairement ce que la variable est censée contenir. Par exemple, des noms de variables tels que altitude, altit ou alt conviennent mieux que x pour exprimer une altitude.


Un bon programmeur doit veiller à ce que ses lignes d’instructions soient faciles à lire.

Sous Python, les noms de variables doivent en outre obéir à quelques règles simples :

  • Un nom de variable est une séquence de lettres (a → z , A → Z) et de chiffres (0 → 9), qui doit toujours commencer par une lettre.
  • Seules les lettres ordinaires sont autorisées. Les lettres accentuées, les cédilles, les espaces, les caractères spéciaux tels que $, #, @, etc. sont interdits, à l'exception du caractère _ (souligné).
  • La casse est significative (les caractères majuscules et minuscules sont distingués).
    Attention : Joseph, joseph, JOSEPH sont donc des variables différentes. Soyez attentifs !

Prenez l'habitude d'écrire l'essentiel des noms de variables en caractères minuscules (y compris la première lettre[6]). Il s'agit d'une simple convention, mais elle est largement respectée. N'utilisez les majuscules qu'à l'intérieur même du nom, pour en augmenter éventuellement la lisibilité, comme dans tableDesMatieres.

En plus de ces règles, il faut encore ajouter que vous ne pouvez pas utiliser comme noms de variables les 33 « mots réservés » ci-dessous (ils sont utilisés par le langage lui-même) :

and def for is raise
as None nonlocal True
assert elif from lambda return
break else global not try
class except if or while
continue False import pass yield
del finally in print
with  


Affectation (ou assignation)

Nous savons désormais comment choisir judicieusement un nom de variable. Voyons à présent comment nous pouvons définir une variable et lui affecter une valeur. Les termes « affecter une valeur » ou « assigner une valeur » à une variable sont équivalents. Ils désignent l’opération par laquelle on établit un lien entre le nom de la variable et sa valeur (son contenu).

En Python comme dans de nombreux autres langages, l’opération d’affectation est représentée par le signe égale[7] :

>>> n=7 # définir n et lui donner la valeur 7
>>> msg = « Quoi de neuf ? » # affecter la valeur « Quoi de neuf ? » à msg
>>> pi = 3.14159 # assigner sa valeur à la variable pi

Les exemples ci-dessus illustrent des instructions d’affectation Python tout à fait classiques. Après qu’on les ait exécutées, il existe dans la mémoire de l’ordinateur, à des endroits différents :

• trois noms de variables, à savoir n, msg et pi ;

• trois séquences d’octets, où sont encodées le nombre entier 7, la chaîne de caractères Quoi de neuf ? et le nombre réel 3, 14159.

Les trois instructions d’affectation ci-dessus ont eu pour effet chacune de réaliser plusieurs opérations dans la mémoire de l’ordinateur :

• créer et mémoriser un nom de variable ;

• lui attribuer un type bien déterminé (ce point sera explicité à la page suivante) ;

• créer et mémoriser une valeur particulière ;

• établir un lien (par un système interne de pointeurs) entre le nom de la variable et l’emplacement mémoire de la valeur correspondante.

On peut mieux se représenter tout cela par un diagramme d’état tel que celui-ci :

n msg pi
7 Quoi de neuf ? 3.14159


Les trois noms de variables sont des références, mémorisées dans une zone particulière de la mémoire que l’on appelle espace de noms, alors que les valeurs correspondantes sont situées ailleurs, dans des emplacements parfois fort éloignés les uns des autres. Nous aurons l’occasion de préciser ce concept plus loin dans ces pages.

Afficher la valeur d’une variable

À la suite de l’exercice ci-dessus, nous disposons donc des trois variables n, msg et pi. Pour afficher leur valeur à l’écran, il existe deux possibilités. La première consiste à entrer au clavier le nom de la variable, puis <Enter>. Python répond en affichant la valeur correspondante :


>>> n

7

>>> msg

’Quoi de neuf ?’

>>> pi

3.14159


Il s’agit cependant là d’une fonctionnalité secondaire de l’interpréteur, qui est destinée à vous faciliter la vie lorsque vous faites de simples exercices à la ligne de commande. À l’intérieur d’un programme, vous utiliserez toujours la fonction print ()[8] :


>>> print (msg)

Quoi de neuf ?

>>> print (n)

7


Remarquez la subtile différence dans les affichages obtenus avec chacune des deux méthodes. La fonction print () n’affiche strictement que la valeur de la variable, telle qu’elle a été encodée, alors que l’autre méthode (celle qui consiste à entrer seulement le nom de la variable) affiche aussi des apostrophes afin de vous rappeler que la variable traitée est du type « chaîne de caractères » : nous y reviendrons.


Dans les versions de Python antérieures à la version 3.0, le rôle de la fonction print () était assuré par une instruction print particulière, faisant d’ailleurs l’objet d’un mot réservé (voir page 14). Cette instruction s’utilisait sans parenthèses. Dans les exercices précédents, il fallait donc entrer « print n » ou « print msg ». Si vous essayez plus tard de faire fonctionner sous Python 3, des programmes écrits dans l’une ou l’autre version ancienne, sachez donc que vous devrez ajouter des parenthèses après chaque instruction print afin de convertir celle-ci en fonction (des utilitaires permettent de réaliser cela automatiquement). Dans ces mêmes versions anciennes, les chaînes de caractères étaient traitées différemment (nous en reparlerons en détail plus loin). Suivant la configuration de votre ordinateur, vous pouviez alors parfois rencontrer quelques effets bizarres avec les chaînes contenant des caractères accentués, tels que par exemple :

>>> msg = « Mon prénom est Chimène »

>>> msg

’Mon prxe9nom est Chimxe8ne’

Ces bizarreries appartiennent désormais au passé, mais nous verrons plus loin qu’un programmeur digne de ce nom doit savoir de quelle manière sont encodés les caractères typographiques rencontrés dans différentes sources de données, car les normes définissant ces encodages ont changé au cours des années, et il faut connaître les techniques qui permettent de les convertir.



Typage des variables

Sous Python, il n’est pas nécessaire d’écrire des lignes de programme spécifiques pour définir le type des variables avant de pouvoir les utiliser. Il vous suffit en effet d’assigner une valeur à un nom de variable pour que celle-ci soit automatiquement créée avec le type qui correspond au mieux à la valeur fournie. Dans l’exercice précédent, par exemple, les variables n, msg et pi ont été créées automatiquement chacune avec un type différent ( « nombre entier » pour n, « chaîne de caractères » pour msg, « nombre à virgule flottante » (ou « float », en anglais) pour pi).

Ceci constitue une particularité intéressante de Python, qui le rattache à une famille particulière de langages où l’on trouve aussi par exemple Lisp, Scheme, et quelques autres. On dira à ce sujet que le typage des variables sous Python est un typage dynamique, par opposition au typage statique qui est de règle par exemple en C++ ou en Java. Dans ces langages, il faut toujours – par des instructions distinctes — d’abord déclarer (définir) le nom et le type des variables, et ensuite seulement leur assigner un contenu, lequel doit bien entendu être compatible avec le type déclaré.

Le typage statique est préférable dans le cas des langages compilés, parce qu’’il permet d’optimiser l’opération de compilation (dont le résultat est un code binaire « figé » ).

Le typage dynamique quant à lui permet d’écrire plus aisément des constructions logiques de niveau élevé (métaprogrammation, réflexivité), en particulier dans le contexte de la programmation orientée objet (polymorphisme). Il facilite également l’utilisation de structures de données très riches telles que les listes et les dictionnaires.



Affectations multiples

Sous Python, on peut assigner une valeur à plusieurs variables simultanément. Exemple :

>>>x = y = 7

>>> x

7

>>> y

7

On peut aussi effectuer des affectations parallèles à l’aide d’un seul opérateur :

>>> a, b = 4, 8.33

>>> a

4

>>> b

8.33

Dans cet exemple, les variables a et b prennent simultanément les nouvelles valeurs 4 et 8, 33.

Les francophones que nous sommes avons pour habitude d’utiliser la virgule comme séparateur décimal, alors que les langages de programmation utilisent toujours la convention en vigueur dans les pays de langue anglaise, c’est-à-dire le point décimal. La virgule, quant à elle, est très généralement utilisée pour séparer différents éléments (arguments, ete.) comme on le voit dans notre

exemple, pour les variables elles-mêmes ainsi que pour les valeurs qu’on leur attribue.



Exercices

2.1 Décrivez le plus clairement et le plus complètement possible ce qui se passe à chacune des trois lignes de l’exemple ci-dessous :

>>> largeur = 20
>>> hauteur = 5 * 9.3
>>> largeur * hauteur
930

2.2 Assignez les valeurs respectives 3, 5, 7 à trois variables a, b, c.
Effectuez l’opération a - b//c. Interprétez le résultat obtenu.



Opérateurs et expressions

On manipule les valeurs et les variables qui les référencent en les combinant avec des opérateurs pour former des expressions. Exemple :

a, b = 7.3, 12
y = 3*a + b/5

Dans cet exemple, nous commençons par affecter aux variables a et b les valeurs 7, 3 et 12. Comme déjà expliqué précédemment, Python assigne automatiquement le type « réel » à la variable a, et le type « entier » à la variable b.

La seconde ligne de l’exemple consiste à affecter à une nouvelle variable y le résultat d’une expression qui combine les opérateurs *, + et / avec les opérandes a, b, 3 et 5. Les opérateurs sont les symboles spéciaux utilisés pour représenter des opérations mathématiques simples, telles l’addition ou la multiplication. Les opérandes sont les valeurs combinées à l’aide des opérateurs.

Python évalue chaque expression qu’on lui soumet, aussi compliquée soit-elle, et le résultat de cette évaluation est toujours lui-même une valeur. À cette valeur, il attribue automatiquement un type, lequel dépend de ce qu’il y a dans l’expression. Dans l’exemple ci-dessus, y sera du type réel, parce que l’expression évaluée pour déterminer sa valeur contient elle-même au moins un réel.

Les opérateurs Python ne sont pas seulement les quatre opérateurs mathématiques de base. Nous avons déjà signalé l’existence de l’opérateur de division entière //. Il faut encore ajouter l’opérateur** pour l’exponentiation, ainsi qu’un certain nombre d’opérateurs logiques, des opérateurs agissant sur les chaînes de caractères, des opérateurs effectuant des tests d’identité ou d’appartenance, ete. Nous reparlerons de tout cela plus loin.

Signalons au passage la disponibilité de l’opérateur modulo, représenté par le caractère typographique %. Cet opérateur fournit le reste de la division entière d’un nombre par un autre. Essayez par exemple :

>>>10 % 3 # (et prenez note de ce qui se passe ! )

>>>10 % 5

Cet opérateur vous sera très utile plus loin, notamment pour tester si un nombre a est divisible par un nombre b. Il suffira en effet de vérifier que a % b donne un résultat égal à zéro.


Exercice

2.3 Testez les lignes d’instructions suivantes. Décrivez dans votre cahier ce qui se passe :

>>> r, pi = 12, 3.14159

>>> s = pi * r ** 2

>>> print (s)

>>> print (type (r), type (pi), type (s))

Quelle est, à votre avis, l’utilité de la fonction type() ?

(Note : les fonctions seront décrites en détail aux chapitres 6 et 7.)



Priorité des opérations

Lorsqu’il y a plus d’un opérateur dans une expression, l’ordre dans lequel les opérations doivent être effectuées dépend de règles de priorité. Sous Python, les règles de priorité sont les mêmes que celles qui vous ont été enseignées au cours de mathématique. Vous pouvez les mémoriser aisément à l’aide d’un « truc » mnémotechnique, l’acronyme PEMDAS :

• P pour parenthèses. Ce sont elles qui ont la plus haute priorité. Elles vous permettent donc de « forcer » l’évaluation d’une expression dans l’ordre que vous voulez.

Ainsi 2.(3-1) = 4, et (1+1)**(5-2) = 8.

• E pour exposants. Les exposants sont évalués ensuite, avant les autres opérations.

Ainsi 2**1+1 = 3 (et non 4), et 3*1**10 = 3 (et non 59049 ! ).

M et D pour multiplication et division, qui ont la même priorité. Elles sont évaluées avant l’addition A et la soustraction S, lesquelles sont donc effectuées en dernier lieu.

Ainsi 2*3-1 = 5 (plutôt que 4), et 2 / 3- 1 = -0.3333… (plutôt que 1.0).

• Si deux opérateurs ont la même priorité, l’évaluation est effectuée de gauche à droite. Ainsi dans l’expression 59*100//60, la multiplication est effectuée en premier, et la machine doit donc ensuite effectuer 5900//60, ce qui donne 98. Si la division était effectuée en premier, le résultat serait 59 (rappelez-vous ici que l’opérateur // effectue une division entière, et vérifiez en effectuant 59*(100//60)).



Composition

Jusqu’ici nous avons examiné les différents éléments d’un langage de programmation, à savoir : les variables, les expressions et les instructions, mais sans traiter de la manière dont nous pouvons les combiner les unes avec les autres.

Or l’une des grandes forces d’un langage de programmation de haut niveau est qu’il permet de construire des instructions complexes par assemblage de fragments divers. Ainsi par exemple, si vous savez comment additionner deux nombres et comment afficher une valeur, vous pouvez combiner ces deux instructions en une seule :

>>> print(17 + 3)

>>> 20

Cela n’a l’air de rien, mais cette fonctionnalité qui paraît si évidente va vous permettre de programmer des algorithmes complexes de façon claire et concise. Exemple :

>>>h, m, s = 15, 27, 34

>>> print( "nombre de secondes écoulées depuis minuit = ", h*3600 + m*60 + s)

Attention, cependant : il y a une limite à ce que vous pouvez combiner ainsi :

Dans une expression, ce que vous placez à la gauche du signe égale doit toujours être une variable, et non une expression. Cela provient du fait que le signe égale n’a pas ici la même signification qu’en mathématique : comme nous l’avons déjà signalé, il s’agit d’un symbole d’affectation (nous plaçons un certain contenu dans une variable) et non un symbole d’égalité. Le symbole d’égalité (dans un test conditionnel, par exemple) sera évoqué un peu plus loin.

Ainsi par exemple, l’instruction m + 1 = b est tout à fait illégale.

Par contre, écrire a = a + 1 est inacceptable en mathématique, alors que cette forme d’écriture est très fréquente en programmation. L’instruction a = a + 1 signifie en l’occurrence « augmenter la valeur de la variable a d’une unité » (ou encore : « incrémenter a » ).

Nous aurons l’occasion de revenir bientôt sur ce sujet. Mais auparavant, il nous faut encore aborder un autre concept de grande importance.






3








Contrôle du flux d’exécution



Dans notre premier chapitre, nous avons vu que l’activité essentielle d’un programmeur est la résolution de problèmes. Or, pour résoudre un problème informatique, il faut toujours effectuer une série d’actions dans un certain ordre. La description structurée de ces actions et de l’ordre dans lequel il convient de les effectuer s’appelle un algorithme.

Le « chemin » suivi par Python à travers un programme est appelé un flux d’exécution, et les constructions qui le modifient sont appelées des instructions de contrôle de flux.

Les structures de contrôle sont les groupes d’instructions qui déterminent l’ordre dans lequel les actions sont effectuées. En programmation moderne, il en existe seulement trois : la séquence[9] et la sélection, que nous allons décrire dans ce chapitre, et la répétition que nous aborderons au chapitre suivant.



Séquence d’instructions

Sauf mention explicite, les instructions d’un programme s’exécutent les unes après les autres, dans l’ordre où elles ont été écrites à l’intérieur du script.

Cette affirmation peut vous paraître banale et évidente à première vue. L’expérience montre cependant qu’un grand nombre d’erreurs sémantiques dans les programmes d’ordinateur sont la conséquence d’une mauvaise disposition des instructions. Plus vous progresserez dans l’art de la programmation, plus vous vous rendrez compte qu’il faut être extrêmement attentif à l’ordre dans lequel vous placez vos instructions les unes derrière les autres. Par exemple, dans la séquence d’instructions suivantes :

>>>a, b = 3, 7

>>>a = b

>>>b = a

>>> print(a, b)

Vous obtiendrez un résultat contraire si vous intervertissez les 2e et 3e lignes.

Python exécute normalement les instructions de la première à la dernière, sauf lorsqu’il rencontre une instruction conditionnelle comme l’instruction if décrite ci-après (nous en rencontrerons trerons d’autres plus loin, notamment à propos des boucles de répétition). Une telle instruction va permettre au programme de suivre différents chemins suivant les circonstances.



Sélection ou exécution conditionnelle

Si nous voulons pouvoir écrire des applications véritablement utiles, il nous faut des techniques permettant d’aiguiller le déroulement du programme dans différentes directions, en fonction des circonstances rencontrées. Pour ce faire, nous devons disposer d’instructions capables de tester une certaine condition et de modifier le comportement du programme en conséquence.

La plus simple de ces instructions conditionnelles est l’instruction if. Pour expérimenter son fonctionnement, veuillez entrer dans votre éditeur Python les deux lignes suivantes :

>>>a = 150

>>> if (a > 100) :

...

La première commande affecte la valeur 150 à la variable a. Jusqu’ici rien de nouveau. Lorsque vous finissez d’entrer la seconde ligne, par contre, vous constatez que Python réagit d’une nouvelle manière. En effet, et à moins que vous n’ayez oublié le caractère « : » à la fin de la ligne, vous constatez que le prompt principal (>>>) est maintenant remplacé par un prompt secondaire constitué de trois points[10].

Si votre éditeur ne le fait pas automatiquement, vous devez à présent effectuer une tabulation (ou entrer 4 espaces) avant d’entrer la ligne suivante, de manière à ce que celle-ci soit indentée (c’est-à-dire en retrait) par rapport à la précédente. Votre écran devrait se présenter maintenant comme suit :

>>>a = 150

>>> if (a > 100) :

...

print("a dépasse la centaine")

Frappez encore une fois <Enter>. Le programme s'exécute, et vous obtenez :

a dépasse la centaine

Recommencez le même exercice, mais avec a = 20 en guise de première ligne : cette fois Python n'affiche plus rien.

L'expression que vous avez placée entre parenthèses est ce que nous appellerons désormais une condition. L'instruction if permet de tester la validité de cette condition. Si la condition est vraie, alors l'instruction que nous avons indentée après le « : » est exécutée. Si la condition est fausse, rien ne se passe. Notez que les parenthèses utilisées ici sont optionnelles sous Python. Nous les avons utilisées pour améliorer la lisibilité. Dans d'autres langages, il se peut qu'elles soient obligatoires. Recommencez encore, en ajoutant deux lignes comme indiqué ci-dessous. Veillez bien à ce que la quatrième ligne débute tout à fait à gauche (pas d’indentation), mais que la cinquième soit à nouveau indentée (de préférence avec un retrait identique à celui de la troisième) :

>>> a = 20
>>> if (a > 100) :
... print « a dépasse la centaine »
... else :
... print « a ne dépasse pas cent »
...

Frappez <Enter> encore une fois. Le programme s’exécute, et affiche cette fois :

a ne dépasse pas cent

Comme vous l’aurez certainement déjà compris, l’instruction else ( « sinon », en anglais) permet de programmer une exécution alternative, dans laquelle le programme doit choisir entre deux possibilités. On peut faire mieux encore en utilisant aussi l’instruction elif (contraction de « else if » ) :

>>> a = 0
>>> if a > 0 :
... print « a est positif »
... elif a < 0 :
... print « a est négatif »
... else :
... print « a est nul »
...



Opérateurs de comparaison

La condition évaluée après l’instruction if peut contenir les opérateurs de comparaison suivants :

x == y # x est égal à y
x ! = y # x est différent de y
x > y # x est plus grand que y
x < y # x est plus petit que y
x >= y # x est plus grand que, ou égal à y
x <= y # x est plus petit que, ou égal à y

Exemple :

>>> a = 7
>>> if (a % 2 == 0) :
... print « a est pair »
... print « parce que le reste de sa division par 2 est nul »
... else :
... print « a est impair »
...

Notez bien que l'opérateur de comparaison pour l'égalité de deux valeurs est constitué de deux signes « égale » et non d'un seul[11]. Le signe « égale » utilisé seul est un opérateur d'affectation, et non un opérateur de comparaison. Vous retrouverez le même symbolisme en C++ et en Java.

Instructions composées – blocs d’instructions

La construction que vous avez utilisée avec l'instruction if est votre premier exemple d'instruction composée. Vous en rencontrerez bientôt d'autres. Sous Python, toutes les instructions composées ont toujours la même structure : une ligne d'en-tête terminée par un double point, suivie d'une ou de plusieurs instructions indentées sous cette ligne d'en-tête. Exemple :

Ligne d’en-tête:
    première instruction du bloc
    ... ...
    ... ...
    dernière instruction du bloc

S'il y a plusieurs instructions indentées sous la ligne d'en-tête, elles doivent l'être exactement au même niveau (comptez un décalage de 4 caractères, par exemple). Ces instructions indentées constituent ce que nous appellerons désormais un bloc d'instructions. Un bloc d'instructions est une suite d'instructions formant un ensemble logique, qui n'est exécuté que dans certaines conditions définies dans la ligne d'en-tête. Dans l'exemple du paragraphe précédent, les deux lignes d'instructions indentées sous la ligne contenant l'instruction if constituent un même bloc logique : ces deux lignes ne sont exécutées - toutes les deux - que si la condition testée avec l'instruction if se révèle vraie, c'est-à-dire si le reste de la division de a par 2 est nul.



Instructions imbriquées

Il est parfaitement possible d'imbriquer les unes dans les autres plusieurs instructions composées, de manière à réaliser des structures de décision complexes. Exemple :

if embranchement == "vertébrés": #1
    if classe == "mammifères": #2
        if ordre == "carnivores": #3
            if famille == "félins": #4
        print("c’est peut-être un chat #5
    print "c'est en tous cas un mammifère" #6
elif classe == 'oiseaux': #7
        print "c'est peut-être un canari" #8
print"la classification des animaux est complexe" #9

Analysez cet exemple. Ce fragment de programme n'imprime la phrase « c'est peut-être un chat » que dans le cas où les quatre premières conditions testées sont vraies.

Pour que la phrase « c'est en tous cas un mammifère » soit affichée, il faut et il suffit que les deux premières conditions soient vraies. L'instruction d'affichage de cette phrase (ligne 4) se trouve en effet au même niveau d’indentation que l’instruction : if ordre == "carnivores" : (ligne 3). Les deux font donc partie d’un même bloc, lequel est entièrement exécuté si les conditions testées aux lignes 1 et 2 sont vraies.

Pour que la phrase « c’est peut-être un canari » soit affichée, il faut que la variable embranchement contienne « vertébrés », et que la variable classe contienne « oiseaux ».

Quant à la phrase de la ligne 9, elle est affichée dans tous les cas, parce qu’elle fait partie du même bloc d’instructions que la ligne 1.



Quelques règles de syntaxe Python

Tout ce qui précède nous amène à faire le point sur quelques règles de syntaxe :


Les limites des instructions et des blocs sont définies par la mise en page

Dans de nombreux langages de programmation, il faut terminer chaque ligne d’instructions par un caractère spécial (souvent le point-virgule). Sous Python, c’’est le caractère de fin de ligne[12] qui joue ce rôle. (Nous verrons plus loin comment outrepasser cette règle pour étendre une instruction complexe sur plusieurs lignes.) On peut également terminer une ligne d’instructions par un commentaire. Un commentaire Python commence toujours par le caractère spécial #. Tout ce qui est inclus entre ce caractère et le saut à la ligne suivant est complètement ignoré par le compilateur.

Dans la plupart des autres langages, un bloc d’instructions doit être délimité par des symboles spécifiques (parfois même par des instructions, telles que begin et end). En C++ et en Java, par exemple, un bloc d’instructions doit être délimité par des accolades. Cela permet d’écrire les blocs d’instructions les uns à la suite des autres, sans se préoccuper ni d’indentation ni de sauts à la ligne, mais cela peut conduire à l’écriture de programmes confus, difficiles à relire pour les pauvres humains que nous sommes. On conseille donc à tous les programmeurs qui utilisent ces langages de se servir aussi des sauts à la ligne et de l’indentation pour bien délimiter visuellement les blocs.

Avec Python, vous devez utiliser les sauts à la ligne et l’indentation, mais en contrepartie vous n’avez pas à vous préoccuper d’autres symboles délimiteurs de blocs. En définitive, Python vous force donc à écrire du code lisible, et à prendre de bonnes habitudes que vous conserverez lorsque vous utiliserez d’autres langages.


Instruction composée : en-tête, double point, bloc d’instructions indenté

Nous aurons de nombreuses occasions d’approfondir le concept de « bloc d’instructions » et de faire des exercices à ce sujet dès le chapitre suivant.

Le schéma ci-contre en résume le principe.
Illustration
  • Les blocs d’instructions sont toujours associés à une ligne d’en-tête contenant une instruction bien spécifique (if, elif, else, while, def,…) se terminant par un double point.


  • Les blocs sont délimités par l’indentation : toutes les lignes d’un même bloc doivent être indentées exactement de la même manière (c’est-à-dire décalées vers la droite d’un même nombre d’espaces). Le nombre d’espaces à utiliser pour l’indentation est quelconque, mais la plupart des programmeurs utilisent des multiples de 4.


  • Notez que le code du bloc le plus externe (bloc 1) ne peut pas lui-même être écarté de la marge de gauche (Il n’est imbriqué dans rien).


Important : Vous pouvez aussi indenter à l’aide de tabulations, mais alors vous devrez faire très attention à ne pas utiliser tantôt des espaces, tantôt des tabulations pour indenter les lignes d’un même bloc. En effet, et même si le résultat paraît identique à l’écran, espaces et tabulations sont des codes binaires distincts : Python considérera donc que ces lignes indentées différemment font partie de blocs différents. Il peut en résulter des erreurs difficiles à déboguer. En conséquence, la plupart des programmeurs préfèrent se passer des tabulations. Si vous utilisez un éditeur « intelligent », vous pouvez escamoter le problème en activant l’option « Remplacer les tabulations par des espaces ».


Les espaces et les commentaires sont normalement ignorés

À part ceux qui servent à l’indentation, en début de ligne, les espaces placés à l’intérieur des instructions et des expressions sont presque toujours ignorés (sauf s’ils font partie d’une chaîne de caractères). Il en va de même pour les commentaires : ceux-ci commencent toujours par un caractère dièse (#) et s’étendent jusqu’à la fin de la ligne courante.






4








Instructions répétitives.



L’une des tâches que les machines font le mieux est la répétition sans erreur de tâches identiques. Il existe bien des méthodes pour programmer ces tâches répétitives. Nous allons commencer par l’une des plus fondamentales : la boucle de répétition construite autour de l’instruction while.



Ré-affectation

Nous ne l’avions pas encore signalé explicitement : il est permis de ré-affecter une nouvelle valeur à une même variable, autant de fois qu’on le souhaite.

L’effet d’une ré-affectation est de remplacer l’ancienne valeur d’une variable par une nouvelle.

>>> altitude = 320
>>> print(altitude)
320
>>> altitude = 375
>>> print(altitude)
375

Ceci nous amène à attirer une nouvelle fois votre attention sur le fait que le symbole égale utilisé sous Python pour réaliser une affectation ne doit en aucun cas être confondu avec un symbole d’égalité tel qu’il est compris en mathématique. Il est tentant d’interpréter l’instruction altitude = 320 comme une affirmation d’égalité, mais ce n’en n’est pas une !
  • Premièrement, l’égalité est commutative, alors que l’affectation ne l’est pas. Ainsi, en mathématique, les écritures a = 7 et 7 = a sont équivalentes, alors qu’une instruction de programmation telle que 375 = altitude serait illégale.
  • Deuxièmement, l’égalité est permanente, alors que l’affectation peut être remplacée comme nous venons de le voir. Lorsqu’en mathématique, nous affirmons une égalité telle que a = b au début d’un raisonnement, alors a continue à être égal à b durant tout le développement qui suit.

En programmation, une première instruction d’affectation peut rendre égales les valeurs de deux variables, et une instruction ultérieure en changer ensuite l’une ou l’autre. Exemple :

>>>a = 5
>>>b = a # a et b contiennent des valeurs égales
>>>b = 2 # a et b sont maintenant différentes


Rappelons ici que Python permet d’affecter leurs valeurs à plusieurs variables simultanément :

>>>a, b, c, d = 3, 4, 5, 7

Cette fonctionnalité de Python est bien plus intéressante encore qu’elle n’en a l’air à première vue. Supposons par exemple que nous voulions maintenant échanger les valeurs des variables a et c (actuellement, a contient la valeur 3, et c la valeur 5 ; nous voudrions que ce soit l’inverse). Comment faire ?


Exercice

4.1 Écrivez les lignes d’instructions nécessaires pour obtenir ce résultat.

À la suite de l’exercice proposé ci-dessus, vous aurez certainement trouvé une méthode, et un professeur vous demanderait certainement de la commenter en classe. Comme il s’agit d’une opération courante, les langages de programmation proposent souvent des raccourcis pour l’effectuer (par exemple des instructions spécialisées, telle l’instruction SWAP du langage Basic). Sous Python, l’affectation parallèle permet de programmer l’échange d’une manière particulièrement élégante :

>>>a, b = b, a

(On pourrait bien entendu échanger d’autres variables en même temps, dans la même instruction.)



Répétitions en boucle – l’instruction while

L’une des tâches que les machines font le mieux est la répétition sans erreur de tâches identiques. Il existe bien des méthodes pour programmer ces tâches répétitives. Nous allons commencer par l’une des plus fondamentales : la boucle construite à partir de l’instruction while.

Veuillez donc entrer les commandes ci-dessous :


>>> a = 0
>>> while (a < 7) : # (n’oubliez pas le double point ! )
...              a = a + 1 # (n’oubliez pas l’indentation ! )
...              print(a)

Frappez encore une fois <Enter>.

Que se passe-t-il ?

Avant de lire les commentaires de la page suivante, prenez le temps d’ouvrir votre cahier et d’y noter cette série de commandes. Décrivez aussi le résultat obtenu, et essayez de l’expliquer de la manière la plus détaillée possible.

Commentaires

Le mot while signifie « tant que » en anglais. Cette instruction utilisée à la seconde ligne indique à Python qu’il lui faut répéter continuellement le bloc d’instructions qui suit, tant que le contenu de la variable a reste inférieur à 7.

Comme l’instruction if abordée au chapitre précédent, l’instruction while amorce une instruction composée. Le double point à la fin de la ligne introduit le bloc d’instructions à répéter, lequel doit obligatoirement se trouver en retrait. Comme vous l’avez appris au chapitre précédent, toutes les instructions d’un même bloc doivent être indentées exactement au même niveau (c’est-à -dire décalées à droite d’un même nombre d’espaces).

Nous avons ainsi construit notre première boucle de programmation, laquelle répète un certain nombre de fois le bloc d’instructions indentées. Voici comment cela fonctionne :

• Avec l’instruction while, Python commence par évaluer la validité de la condition fournie entre parenthèsesstelles-ci sont optionnelles, nous ne les avons utilisées que pour clarifier notre explication).
• Si la condition se révèle fausse, alors tout le bloc qui suit est ignoré et l’exécution du programme se termine[13]
• Si la condition est vraie, alors Python exécute tout le bloc d’instructions constituant le corps de la boucle, c’est-à -dire :

– l’instruction a = a + 1 qui incrémente d’une unité le contenu de la variable a (ce qui signifie que l’on affecte à la variable a une nouvelle valeur, qui est égale à la valeur précédente augmentée d’une unité).

– l’appel de la fonction print() pour afficher la valeur courante de la variable a.

• lorsque ces deux instructions ont été exécutées, nous avons assisté à une première itération, et le programme boucle, c’’est-à -dire que l’exécution reprend à la ligne contenant l’instruction while. La condition qui s’y trouve est à nouveau évaluée, et ainsi de suite. Dans notre exemple, si la condition a < 7 est encore vraie, le corps de la boucle est exécuté une nouvelle fois et le bouclage se poursuit.


Remarques
• La variable évaluée dans la condition doit exister au préalable (il faut qu’’on lui ait déjà affecté au moins une valeur).
• Si la condition est fausse au départ, le corps de la boucle n’est jamais exécuté.
• Si la condition reste toujours vraie, alors le corps de la boucle est répété indéfiniment (tout au moins tant que Python lui-même continue à fonctionner). Il faut donc veiller à ce que le corps de la boucle contienne au moins une instruction qui change la valeur d’une variable intervenant dans la condition évaluée par while, de manière à ce que cette condi tion puisse devenir fausse et la boucle se terminer.

Exemple de boucle sans fin (à éviter !) :


>>> n = 3
>>> while n < 5:
...         print (hello !)



Élaboration de tables

Recommencez à présent le premier exercice, mais avec la petite modification ci-dessous :


>>> a = 0
>>> while a < 12 :
…         a = a +1
…         print (a, a**2, a**3)

Vous devriez obtenir la liste des carrés et des cubes des nombres de 1 à 12.

Notez au passage que l’instruction print() permet d’afficher plusieurs expressions l’une à la suite de l’autre sur la même ligne : il suffit de les séparer par des virgules. Python insère automatiquement un espace entre les éléments affichés.



Construction d’une suite mathématique

Le petit programme ci-dessous permet d’afficher les dix premiers termes d’une suite appelée « Suite de Fibonacci ». Il s’agit d’une suite de nombres, dont chaque terme est égal à la somme des deux termes qui le précèdent. Analysez ce programme (qui utilise judicieusement l'affectation multiple). Décrivez le mieux possible le rôle de chacune des instructions.


>>> a, b, c = 1, 1, 1
>>> while c < 11 :
…         print (b, end =" ")
…         a, b, c = b, a+ b, c + 1

Lorsque vous lancez l’exécution de ce programme, vous obtenez :


1 2 3 5 8 13 21 34 55 89

Les termes de la suite de Fibonacci sont affichés sur la même ligne. Vous obtenez ce résultat grâce au second argument end =" " fourni à l’instruction print(). Par défaut, la fonction print() ajoute en effet un caractère de saut à la ligne à toute valeur qu'on lui demande d'afficher. L'argument end =" " signifie que vous souhaitez remplacer le saut à la ligne. Si vous supprimez cet argument, les nombres seront affichés l’un en-dessous de l’autre.

Dans vos programmes futurs, vous serez très souvent amenés à mettre au point des boucles de répétition comme celle que nous analysons ici. Il s’agit d’une question essentielle, que vous devez apprendre à maîtriser parfaitement. Soyez sûr que vous y arriverez progressivement, à force d’exercices.

Lorsque vous examinez un problème de cette nature, vous devez considérer les lignes d’instruction, bien entendu, mais surtout décortiquer les états successifs des différentes variables impliquées impliquées dans la boucle. Cela n’est pas toujours facile, loin de là. Pour vous aider à y voir plus clair, prenez la peine de dessiner sur papier une table d’états similaire à celle que nous reproduisons ci-dessous pour notre programme « suite de Fibonacci » :

Variables a b c
Valeurs initiales 1 1 1
Valeurs prises
successivement, au
cours des itérations
1
2
3
5
2
3
5
8
2
3
4
5
Expression de
remplacement
b a+b c+1

Dans une telle table, on effectue en quelque sorte « à la main » le travail de l’ordinateur, en indiquant ligne par ligne les valeurs que prendront chacune des variables au fur et à mesure des itérations successives. On commence par inscrire en haut du tableau les noms des variables concernées. Sur la ligne suivante, les valeurs initiales de ces variables (valeurs qu’elles possèdent avant le démarrage de la boucle). Enfin, tout en bas du tableau, les expressions utilisées dans la boucle pour modifier l’état de chaque variable à chaque itération.

On remplit alors quelques lignes correspondant aux premières itérations. Pour établir les valeurs d’une ligne, il suffit d’appliquer à celles de la ligne précédente, l’expression de remplacement qui se trouve en bas de chaque colonne. On vérifie ainsi que l’on obtient bien la suite recherchée. Si ce n’est pas le cas, il faut essayer d’autres expressions de remplacement.


Exercices :

4.2. Écrivez un programme qui affiche les 20 premiers termes de la table de multiplication par 7.

4.3. Écrivez un programme qui affiche une table de conversion de sommes d’argent exprimées en euros, en dollars canadiens. La progression des sommes de la table sera « géométrique », comme dans l’exemple ci-dessous :

1 euro(s) = 1.65 dollar(s)
2 euro(s) = 3.30 dollar(s)
4 euro(s) = 6.60 dollar(s)
8 euro(s) = 13.20 dollar(s)
etc. (S’arrêter à 16384 euros)

4.4. Écrivez un programme qui affiche une suite de 12 nombres dont chaque terme soit égal au triple du terme précédent.



Premiers scripts, ou : Comment conserver nos programmes ?

Jusqu’à présent, vous avez toujours utilisé Python en mode interactif (c’est-à-dire que vous avez à chaque fois entré les commandes directement dans l’interpréteur, sans les sauvegarder au préalable dans un fichier). Cela vous a permis d’apprendre très rapidement les bases du langage, par expérimentation directe. Cette façon de faire présente toutefois un gros inconvénient : toutes les séquences d’instructions que vous avez écrites disparaissent irrémédiablement dès que vous fermez l’interpréteur. Avant de poursuivre plus avant votre étude, il est donc temps que vous appreniez à sauvegarder vos programmes dans des fichiers, sur disque dur ou disquette, de manière à pouvoir les retravailler par étapes successives, les transférer sur d’autres machines, etc.

Pour ce faire, vous allez désormais rédiger vos séquences d’instructions dans un éditeur de textes quelconque (par exemple Kate, Gedit, Geany… sous Linux, Wordpad, Geany, Komodo editor,… sous Windows, ou encore l’éditeur incorporé dans l'interface de développement IDLE qui fait partie dee la distribution de Python pour Windows). Ainsi vous écrirez un script, que vous pourrez ensuite sauvegarder, modifier, copier, etc. comme n’importe quel autre texte traité par ordinateur[14].La figure ci-dessous illustre l’utilisation de l’éditeur Gedit sous Linux (Ubuntu) :

Python 4 1.png

Par la suite, lorsque vous voudrez tester l’exécution de votre programme, il vous suffira de lancer l’interpréteur Python en lui fournissant (comme argument) le nom du fichier qui contient le script. Par exemple, si vous avez placé un script dans un fichier nommé « MonScript », il suffira d’entrer la commande suivante dans une fenêtre de terminal pour que ce script s’exécute :

python3 MonScript[15]

Pour faire mieux encore, veillez à donner au fichier un nom qui se termine par l’extension .py

Si vous respectez cette convention, vous pourrez aussi lancer l’exécution du script, simplement en cliquant sur son nom ou sur l’icône correspondante dans le gestionnaire de fichiers (c’est-à-dire l’explorateur, sous Windows, ou bien Nautilus, Konqueror, sous Linux).

Ces gestionnaires graphiques « savent » en effet qu’il doivent lancer l’interpréteur Python chaque fois que leur utilisateur essaye d’ouvrir un fichier dont le nom se termine par .py (cela suppose bien entendu qu’ils aient été correctement configurés). La même convention permet en outre aux éditeurs « intelligents » de reconnaître automatiquement les scripts Python et d’adapter leur coloration syntaxique en conséquence.

Un script Python contiendra des séquences d’instructions identiques à celles que vous avez expérimentées jusqu’à présent. Puisque ces séquences sont destinées à être conservées et relues plus tard par vous-même ou par d’autres, il vous est très fortement recommandé d’expliciter vos scripts le mieux possible, en y incorporant de nombreux commentaires. La principale difficulté de la programmation consiste en effet à mettre au point des algorithmes corrects. Afin que ces algorithmes puissent être vérifiés, corrigés, modifiés, etc. dans de bonnes conditions, il est essentiel que leur auteur les décrive le plus complètement et le plus clairement possible. Et le meilleur emplacement pour cette description est le corps même du script (ainsi elle ne peut pas s’égarer).

Un bon programmeur veille toujours à insérer un grand nombre de commentaires dans ses scripts. En procédant ainsi, non seulement il facilite la compréhension de ses algorithmes pour d’autres lecteurs éventuels, mais encore il se force lui-même à avoir les idées plus claires.

On peut insérer des commentaires quelconques à peu près n’importe où dans un script. Il suffit de les faire précéder d’un caractère #. Lorsqu’il rencontre ce caractère, l’interpréteur Python ignore tout ce qui suit, jusqu’à la fin de la ligne courante.

Comprenez bien qu’il est important d’inclure des commentaires au fur et à mesure de l’avancement de votre travail de programmation. N’attendez pas que votre script soit terminé pour les ajouter « après coup ». Vous vous rendrez progressivement compte qu’un programmeur passe énormément de temps à relire son propre code (pour le modifier, y rechercher des erreurs, etc). Cette relecture sera grandement facilitée si le code comporte de nombreuses explications et remarques.

Ouvrez donc un éditeur de texte, et rédigez le script ci-dessous :

  1. Premier essai de script Python
  2. petit programme simple affichant une suite de Fibonacci, c.à.d. une suite
  3. de nombres dont chaque terme est égal à la somme des deux précédents.


a, b, c = 1, 1, 1 # a & b servent au calcul des termes successifs
                              # c est un simple compteur
print(b) # affichage du premier terme
while c<15: # nous afficherons 15 termes au total


a, b, c = b, a+b, c+1
print b

Afin de vous montrer tout de suite le bon exemple, nous commençons ce script par trois lignes de commentaires, qui contiennent une courte description de la fonctionnalité du programme. Prenez l'habitude de faire de même dans vos propres scripts.

Certaines lignes de code sont également elle-mêmes documentées. Si vous procédez comme nous l'avons fait, c'est-à-dire en insérant des commentaires à la droite des instructions correspondantes, veillez à les écarter suffisamment de celles-ci, afin de ne pas gêner leur lisibilité.

Lorsque vous aurez bien vérifié votre texte, sauvegardez-le et exécutez-le.

Bien que ce ne soit pas indispensable, nous vous recommandons une fois encore de choisir pour vos scripts des noms de fichiers se terminant par l'extension .py Cela aide beaucoup à les identifier comme tels dans un répertoire. Les gestionnaires graphiques de fichiers (explorateur Windows, Nautilus, Konqueror) se servent d'ailleurs de cette extension pour leur associer une icône spécifique. Évitez cependant de choisir des noms qui risqueraient d'être déjà attribués à des modules python existants : des noms tels que math.py ou tkinter.py, par exemple, sont à proscrire !

Si vous travaillez en mode texte sous Linux, ou dans une fenêtre MS-DOS, vous pouvez exécuter votre script à l'aide de la commande python3 suivie du nom du script. Si vous travaillez en mode graphique sous Linux, vous pouvez ouvrir une fenêtre de terminal et faire la même chose :

python3 monScript.py

Dans un gestionnaire graphique de fichiers, vous pouvez en principe lancer l'exécution de votre script en effectuant un (double ?) clic de souris sur l'icône correspondante. Ceci ne pourra cependant fonctionner que si c'est bien Python 3 qui a été désigné comme interpréteur par défaut pour les fichiers comportant l'extension .py (des problèmes peuvent en effet apparaître si plusieurs versions de Python sont installées sur votre machine – voyez votre professeur ou votre gourou local pour détailler ces questions).

Si vous travaillez avec IDLE, vous pouvez lancer l'exécution du script en cours d'édition, directement à l'aide de la combinaison de touches <Ctrl-F5>. Dans d'autres environnements de travail spécifiquement dédiés à Python, tels que Geany, vous trouverez également des icônes et/ou des raccourcis clavier pour lancer l'exécution (il s'agit souvent de la touche F5). Consultez votre professeur ou votre gourou local concernant les autres possibilités de lancement éventuelles sur différents systèmes d'exploitation.


Problèmes éventuels liés aux caractères accentués
Si vous avez rédigé votre script avec un logiciel éditeur récent (tels ceux que nous avons déjà indiqués), le script décrit ci-dessus devrait s'exécuter sans problème avec la version actuelle de Python 3. Si votre logiciel éditeur est ancien ou mal configuré, par contre, il se peut que vous obteniez un message d'erreur similaire à celui-ci :


File "fibo2.py", line 2
SyntaxError: Non-UTF-8 code starting with '\xe0' in file fibo2.py on line 2,
but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

Ce message vous indique que le script contient des caractères typographiques encodés suivant une norme ancienne (vraisemblablement la norme ISO-8859-1 ou Latin-1).

Nous détaillerons les différentes normes d’encodage plus loin dans ce livre. Pour l’instant, il vous suffit de savoir que vous devez dans ce cas :

  • soit reconfigurer votre éditeur de textes pour qu’il encode les caractères en Utf-8 (ou vous procurer un autre éditeur fonctionnant suivant cette norme). C’est la meilleure solution, car ainsi vous serez certain à l’avenir de travailler en accord avec les conventions de standardisation actuelles, qui finiront tôt ou tard par remplacer partout les anciennes.
  • soit inclure le pseudo-commentaire suivant au début de tous vos scripts (obligatoirement à la 1e ou à la 2e ligne) :

# -*- coding:Latin-1 -*-

Le pseudo-commentaire ci-dessus indique à Python que vous utilisez dans votre script le jeu de caractères accentués ASCII étendu correspondant aux principales langues de l’Europe occidentale (Français, Allemand, Portugais, etc.), encodé sur un seul octet suivant la norme ISO-8859-1, laquelle est souvent désignée aussi par l’étiquette Latin-1.

Python peut traiter correctement les caractères encodés suivant toute une série de normes, mais il faut alors lui signaler laquelle vous utilisez à l’aide d’un pseudo-commentaire en début de script. Sans cette indication, Python considère que vos scripts ont été encodés en Utf-8[16] ], suivant en cela la nouvelle norme Unicode, laquelle a été mise au point pour standardiser la représentation numérique de tous les caractères spécifiques des différentes langues mondiales, ainsi que les symboles mathématiques, scientifiques, etc. Il existe plusieurs représentations ou encodages de cette norme, et nous devrons approfondir cette question plus loin[17], mais pour l’instant il vous suffit de savoir que l’encodage le plus répandu sur les ordinateurs récents est Utf-8. Dans ce système, les caractères standard (ASCII) sont encore encodés sur un seul octet, ce qui assure une certaine compatibilité avec l’ancienne norme d’encodage Latin-1, mais les autres caractères (parmi lesquels nos caractères accentués) peuvent être encodés sur 2, 3, ou même parfois 4 octets.

Nous apprendrons comment gérer et convertir ces différents encodages, lorsque nous étudierons plus en détail le traitement des fichiers texte (au chapitre 9).



Exercices

4.5 Écrivez un programme qui calcule le volume d’un parallélépipède rectangle dont sont fournis au départ la largeur, la hauteur et la profondeur. 4.6 Écrivez un programme qui convertit un nombre entier de secondes fourni au départ en un nombre d’années, de mois, de jours, de minutes et de secondes (utilisez l’opérateur modulo : %).

4.7 Écrivez un programme qui affiche les 20 premiers termes de la table de multiplication par 7, en signalant au passage (à l’aide d’une astérisque) ceux qui sont des multiples de 3. Exemple : 7 14 21 * 28 35 42 * 49…

4.8 Écrivez un programme qui calcule les 50 premiers termes de la table de multiplication par 13, mais n’affiche que ceux qui sont des multiples de 7.

4.9 Écrivez un programme qui affiche la suite de symboles suivante :

*
**
***
****
*****
******
*******






5








Principaux types de données



Dans le chapitre 2, nous avons déjà manipulé des données de différents types : des nombres entiers ou réels, et des chaînes de caractères. Il est temps à présent d'examiner d'un peu plus près ces types de données, et également de vous en faire découvrir d'autres.



Les données numériques

Dans les exercices réalisés jusqu'à présent, nous avons déjà utilisé des données de deux types : les nombres entiers ordinaires et les nombres réels (aussi appelés nombres à virgule flottante). Tâchons de mettre en évidence les caractéristiques (et les limites) de ces concepts.



Le type integer

Supposons que nous voulions modifier légèrement notre précédent exercice sur la suite de Fibonacci, de manière à obtenir l'affichage d'un plus grand nombre de termes. A priori, il suffit de modifier la condition de bouclage, dans la deuxième ligne. Avec while c <50: , nous devrions obtenir quarante-neuf termes. Modifions donc légèrement l'exercice, de manière à afficher aussi le type de la variable principale :

>>> a, b, c = 1, 1, 1
>>> while c <50:
     print(c, ":", b, type(b))
     a, b, c = b, a+b, c+1
...
...
... (affichage des 43 premiers termes)
...
44 : 1134903170 <class 'int'>
45 : 1836311903 <class 'int'>
46 : 2971215073 <class 'int'>
47 : 4807526976 <class 'int'>
48 : 7778742049 <class 'int'>
49 : 12586269025 <class 'int'>

Que pouvons-nous constater ?

Il semble que Python soit capable de traiter des nombres entiers de taille illimitée. La fonction type() nous permet de vérifier à chaque itération que le type de la variable b reste bien en permanence de ce type.

L'exercice que nous venons de réaliser pourrait cependant intriguer ceux d'entre vous qui s'interrogent sur la représentation « interne » des nombres dans un ordinateur. Vous savez probablement en effet que le « cœur » de celui-ci est constitué par un circuit intégré électronique (une « puce » de silicium) à très haut degré d'intégration, qui peut effectuer plus d'un milliard d'opérations en une seule seconde, mais seulement sur des nombres binaires de taille limitée : 32 bits actuellement[18]. Or, la gamme de valeurs décimales qu'il est possible d'encoder sous forme de nombres binaires de 32 bits s'étend de -2147483648 à +2147483647.

Les opérations effectuées sur des entiers compris entre ces deux limites sont donc toujours très rapides, parce que le processeur est capable de les traiter directement. En revanche, lorsqu'il est question de traiter des nombres entiers plus grands, ou encore des nombres réels (nombres « à virgule flottante »), les logiciels que sont les interpréteurs et compilateurs doivent effectuer un gros travail de codage/décodage, afin de ne présenter en définitive au processeur que des opérations binaires sur des nombres entiers, de 32 bits au maximum.

Vous n'avez pas à vous préoccuper de ces considérations techniques. Lorsque vous lui demandez de traiter des entiers quelconques, Python les transmet au processeur sous la forme de nombres binaires de 32 bits chaque fois que cela est possible, afin d'optimiser la vitesse de calcul et d'économiser l'espace mémoire. Lorsque les valeurs à traiter sont des nombres entiers se situant au-delà des limites indiquées plus haut, leur encodage dans la mémoire de l'ordinateur devient plus complexe, et leur traitement par le processeur nécessite alors plusieurs opérations successives, mais tout cela se fait automatiquement, sans que vous n'ayez à vous en soucier[19].

Vous pouvez donc effectuer avec Python des calculs impliquant des valeurs entières comportant un nombre de chiffres significatifs quelconque. Ce nombre n'est limité en effet que par la taille de la mémoire disponible sur l'ordinateur utilisé. Il va de soi cependant que les calculs impliquant de très grands nombres devront être décomposés par l'interpréteur en calculs multiples sur des nombres plus simples, ce qui pourra nécessiter un temps de traitement considérable dans certains cas.


Exemple :


>>> a, b, c = 3, 2, 1
>>> while c < 15:
print(c, ": ", b)
a, b, c = b, a*b, c+1

1 : 2
2 : 6
3 : 12
4 : 72
5 : 864
6 : 62208
7 : 53747712
8 : 3343537668096
9 : 179707499645975396352
10 : 600858794305667322270155425185792
11 : 107978831564966913814384922944738457859243070439030784
12 : 64880030544660752790736837369104977695001034284228042891827649456186234
582611607420928
13 : 70056698901118320029237641399576216921624545057972697917383692313271754
88362123506443467340026896520469610300883250624900843742470237847552
14 : 45452807645626579985636294048249351205168239870722946151401655655658398
64222761633581512382578246019698020614153674711609417355051422794795300591700
96950422693079038247634055829175296831946224503933501754776033004012758368256
>>>


8 : 3343537668096
9 : 179707499645975396352
10 : 600858794305667322270155425185792
11 : 107978831564966913814384922944738457859243070439030784
12 : 64880030544660752790736837369104977695001034284228042891827649456186234
582611607420928
13 : 70056698901118320029237641399576216921624545057972697917383692313271754
88362123506443467340026896520469610300883250624900843742470237847552
14 : 45452807645626579985636294048249351205168239870722946151401655655658398
64222761633581512382578246019698020614153674711609417355051422794795300591700
96950422693079038247634055829175296831946224503933501754776033004012758368256
>>>

Dans l'exemple ci-dessus, la valeur des nombres affichés augmente très rapidement, car chacun d'eux est égal au produit des deux termes précédents.

Vous pouvez bien évidemment continuer cette suite mathématique plus loin si vous voulez. La progression continue avec des nombres de plus en plus gigantesques, mais la vitesse de calcul diminue au fur et à mesure.

Note complémentaire : les entiers de valeur comprise entre les deux limites indiquées plus haut occupent chacun 32 bits dans la mémoire de l'ordinateur. Les très grands entiers occupent une place variable, en fonction de leur taille.



Le type float

Vous avez déjà rencontré précédemment cet autre type de donnée numérique : le type « nombre réel », ou « nombre à virgule flottante », désigné en anglais par l'expression floatingpointnumber, et que pour cette raison on appellera type float sous Python.

Ce type autorise les calculs sur de très grands ou très petits nombres (données scientifiques, par exemple), avec un degré de précision constant.

Pour qu'une donnée numérique soit considérée par Python comme étant du type float, il suffit qu'elle contienne dans sa formulation un élément tel qu'un point décimal ou un exposant de 10.

Par exemple, les données :


3.14 10. .001 1e100 3.14e-10

sont automatiquement interprétées par Python comme étant du type float.

Essayons donc ce type de données dans un nouveau petit programme (inspiré du précédent) :


>>> a, b, c = 1., 2., 1 # => a et b seront du type 'float'
>>> while c <18:
... a, b, c = b, b*a, c+1
... print(b)

2.0
4.0
8.0


32.0
256.0
8192.0
2097152.0
17179869184.0
3.6028797019e+16
6.18970019643e+26
2.23007451985e+43
1.38034926936e+70
3.07828173409e+113
4.24910394253e+183
1.30799390526e+297
        Inf
        Inf

Comme vous l’aurez certainement bien compris, nous affichons cette fois encore une série dont les termes augmentent extrêmement vite, chacun d’eux étant égal au produit des deux précédents. Au huitième terme, nous dépassons déjà largement la capacité d’un integer. Au neuvième terme, Python passe automatiquement à la notation scientifique ( « e+n » signifie en fait : « fois dix à l’exposant n » ). Après le quinzième terme, nous assistons à nouveau à un dépassement de capacité (sans message d’erreur) : les nombres vraiment trop grands sont tout simplement notés « inf » (pour « infini » ).

Le type float utilisé dans notre exemple permet de manipuler des nombres (positifs ou négatifs) compris entre 10-308 et 10308 avec une précision de 12 chiffres significatifs. Ces nombres sont encodés d’une manière particulière sur 8 octets (64 bits) dans la mémoire de la machine : une partie du code correspond aux 12 chiffres significatifs, et une autre à l’ordre de grandeur (exposant de 10).


Exercices

5.1 Écrivez un programme qui convertisse en radians un angle fourni au départ en degrés, minutes, secondes.

5.2 Écrivez un programme qui convertisse en degrés, minutes, secondes un angle fourni au départ en radians.

5.3 Écrivez un programme qui convertisse en degrés Cessius une température exprimée au départ en degrés Fahrenheit, ou l’inverse.

La formule de conversion est : TF = TC * 1,8 + 32

5.4 Écrivez un programme qui calcule les intérêts accumulés chaque année pendant 20 ans, par capitalisation d’une somme de 100 euros placée en banque au faux fixe de 4, 3 %

5.5 Une légende de l’Inde ancienne raconte que le jeu d’échecs a été inventé par un vieux sage, que son roi voulut remercier en lui affirmant qu’il lui accorderait n’importe quel cadeau en récompense. Le vieux sage demanda qu’on lui fournisse simplement un peu de riz pour ses vieux jours, et plus précisément un nombre de grains de riz suffisant pour que l’on puisse en déposer 1 seul sur la première case du jeu qu’il venait d’inventer, deux sur la suivante, quatre sur la troisième, et ainsi de suite jusqu’à la 64 e case. Écrivez un programme Python qui affiche le nombre de grains à déposer sur chacune des 64 cases du jeu. Calculez ce nombre de deux manières :

  • Le nombre exact de grains (nombre entier) ;
  • Le nombre de grains en notation scientifique (nombre réel).




Les données alphanumériques

Jusqu’à présent nous n’avons manipulé que des nombres. Mais un programme d’ordinateur peut également traiter des caractères alphabétiques, des mots, des phrases, ou des suites de symboles quelconques. Dans la plupart des langages de programmation, il existe pour cet usage des structures de données particulières que l’on appelle « chaînes de caractères ».


Nous apprendrons plus loin (au chapitre 10) qu’il ne faut pas confondre les notions de « chaîne de caractères » et « séquence d’octets » comme le faisaient abusivement les langages de programmation anciens (dont les premières versions de Python). Pour l’instant, contentons-nous de nous réjouir que Python traite désormais de manière parfaitement cohérente toutes les chaînes de caractères, ceux-ci pouvant faire partie d’alphabets quelconques[20]


Le type string

Une donnée de type string peut se définir en première approximation comme une suite quelconque de caractères. Dans un script python, on peut délimiter une telle suite de caractères, soit par des apostrophes (simple quotes), soit par des guillemets (double quotes). Exemples :


>>> phrase1 =’les œufs durs.’
>>> phrase2 =’ « Oui », répondit-il,’
>>> phrase3 = « j’aime bien »
>>> print(phrase2, phrase3, phrase1)
« Oui », répondit-il, j’aime bien les œufs durs.

Les 3 variables phrase1, phrase2, phrase3 sont donc des variables de type string.

Remarquez l’utilisation des guillemets pour délimiter une chaîne dans laquelle il y a des apostrophes, ou l’utilisation des apostrophes pour délimiter une chaîne qui contient des guillemets. Remarquez aussi encore une fois que la fonction print() insère un espace entre les éléments affichés. Le caractère spécial « \ » (antislash) permet quelques subtilités complémentaires :

  • En premier lieu, il permet d’écrire sur plusieurs lignes une commande qui serait trop longue pour tenir sur une seule (cela vaut pour n’importe quel type de commande).
  • À l'intérieur d'une chaîne de caractères, l'antislash permet d'insérer un certain nombre de codes spéciaux (sauts à la ligne, apostrophes, guillemets, etc.). Exemples :


>>> txt3 = '"N\'est-ce pas ?" répondit-elle.'
>>> print(txt3)
"N'est-ce pas ?" répondit-elle.
>>> Salut = "Ceci est une chaîne plutôt longue\n contenant plusieurs lignes \
...de texte (Ceci fonctionne\n de la même façon en C/C++.\n\
...         Notez que les blancs en début\n de ligne sont significatifs.\n"
>>> print(Salut)
Ceci est une chaîne plutôt longue
 contenant plusieurs lignes de texte (Ceci fonctionne
 de la même façon en C/C++.
        Notez que les blancs en début
de ligne sont significatifs.



Remarques
  • La séquence \n dans une chaîne provoque un saut à la ligne.
  • La séquence \' permet d'insérer une apostrophe dans une chaîne délimitée par des apostrophes. De la même manière, la séquence \" permet d'insérer des guillemets dans une chaîne délimitée elle-même par des guillemets.
  • Rappelons encore ici que la casse est significative dans les noms de variables (il faut respecter scrupuleusement le choix initial de majuscules ou minuscules).


Triple quotes

Pour insérer plus aisément des caractères spéciaux ou « exotiques » dans une chaîne, sans faire usage de lantislash, ou pour faire accepter lantislash lui-même dans la chaîne, on peut encore délimiter la chaîne à l'aide de triplesguillemets ou de triplesapostrophes :


>>> a1 = """
... Usage: trucmuche[OPTIONS]
... { -h
... -H hôte
... }"""

>>> print(a1)

Usage: trucmuche[OPTIONS]
{ -h
 -H hôte
}



Accès aux caractères individuels d'une chaîne

Les chaînes de caractères constituent un cas particulier d'un type de données plus général que l'on appelle des données composites. Une donnée composite est une entité qui rassemble dans une seule structure un ensemble d'entités plus simples : dans le cas d'une chaîne de caractères, par exemple, ces entités plus simples sont évidemment les caractères eux-mêmes. En fonction des circonstances, nous souhaiterons traiter la chaîne de caractères, tantôt comme un seul objet, tantôt comme un seul objet, tantôt comme une collection de caractères distincts. Un langage de programmation tel que Python doit donc être pourvu de mécanismes qui permettent d'accéder séparément à chacun des caractères d'une chaîne. Comme vous allez le voir, cela n'est pas bien compliqué.

Python considère qu'une chaîne de caractères est un objet de la catégorie des séquences, lesquelles sont des collections ordonnées d'éléments. Cela signifie simplement que les caractères d'une chaîne sont toujours disposés dans un certain ordre. Par conséquent, chaque caractère de la chaîne peut être désigné par sa place dans la séquence, à l'aide d'un index.

Pour accéder à un caractère bien déterminé, on utilise le nom de la variable qui contient la chaîne et on lui accole, entre deux crochets, l'index numérique qui correspond à la position du caractère dans la chaîne.

Attention cependant : comme vous aurez l'occasion de le vérifier par ailleurs, les données informatiques sont presque toujours numérotées à partir de zéro (et non à partir de un). C'est le cas pour les caractères d'une chaîne.

Exemple :


>>> ch = "Christine"
>>> print(ch[0], ch[3], ch[5])
C i t

Vous pouvez recommencer l'exercice de l'exemple ci-dessus en utilisant cette fois un ou deux caractères « non-ASCII », tels que lettres accentuées, cédilles, etc. Contrairement à ce qui pouvait se passer dans certains cas avec les versions de Python antérieures à la version 3.0, vous obtenez sans surprise les résultats attendus :


>>> ch ="Noël en Décembre"
>>> print(ch[1],ch[2],ch[3],ch[4],ch[8],ch[9],ch[10],ch[11],ch[12])
o ë l D é c e m

Ne vous préoccupez pas pour l'instant de savoir de quelle manière exacte Python mémorise et traite les caractères typographiques dans la mémoire de l'ordinateur. Sachez cependant que la technique utilisée exploite la norme internationale unicode. qui permet de distinguer de façon univoque n'importe quel caractère de n'importe quel alphabet. Vous pourrez donc mélanger dans une même chaîne des caractères latins, grecs, cyrilliques, arabes, ... (y compris les caractères accentués), ainsi que des symboles mathématiques, des pictogrammes, etc. Nous verrons au chapitre 10 comment faire apparaître d'autres caractères que ceux qui sont directement accessibles au clavier.



Opérations élémentaires sur les chaînes

Python intègre de nombreuses fonctions qui permettent d'effectuer divers traitements sur les chaînes de caractères (conversions majuscules/minuscules, découpage en chaînes plus petites, recherche de mots, etc.). Une fois de plus, cependant, nous devons vous demander de patienter : ces questions ne seront développées qu'à partir du chapitre 10. Pour l'instant, nous pouvons nous contenter de savoir qu'il est possible d'accéder individuellement à chacun des caractères d'une chaîne, comme cela a été expliqué dans la section précédente. Sachons en outre que l'on peut aussi :

  • Assembler plusieurs petites chaînes pour en construire de plus grandes. Cette opération s'appelle concaténation et on la réalise sous Python à l'aide de l'opérateur + (cet opérateur réalise donc l'opération d'addition lorsqu'on l'applique à des nombres, et l'opération de concaténation lorsqu'on l'applique à des chaînes de caractères). Exemple :


a =’Petit poisson’
b =’deviendra grand’
c = a + b
print(c)
petit poisson deviendra grand

  • Déterminer la longueur (c'est-à-dire le nombre de caractères) d'une chaîne, en faisant appel à la fonction intégrée len() :


>>> ch = ' Georges '
>>> print(len(ch))
7

Cela marche tout aussi bien si la chaîne contient des caractères accentués :


>>> ch = ' René '
>>> print(len(ch))
4

  • Convertir en nombre véritable une chaîne de caractères qui représente un nombre. Exemple :


>>> ch = '8647'
>>> print(ch + 45)
→ *** erreur *** : on ne peut pas additionner une chaîne et un nombre
>>> n = int(ch)
>>> print(n + 65)
8712 # OK : on peut additionner 2 nombres

Dans cet exemple, la fonction intégrée int() convertit la chaîne en nombre entier. Il serait également possible de convertir une chaîne de caractères en nombre réel, à l'aide de la fonction intégrée float().


Exercices

5.6 Écrivez un script qui détermine si une chaîne contient ou non le caractère « e ».

5.7 Écrivez un script qui compte le nombre d'occurrences du caractère « e » dans une chaîne.

5.8 Écrivez un script qui recopie une chaîne (dans une nouvelle variable), en insérant des astérisques entre les caractères.

Ainsi par exemple, « gaston » devra devenir « g*a*s*t*o*n »

5.9 Écrivez un script qui recopie une chaîne (dans une nouvelle variable) en l'inversant.

Ainsi par exemple, « zorglub » deviendra « bulgroz ». 5.10 En partant de l'exercice précédent, écrivez un script qui détermine si une chaîne de caractères donnée est un palindrome (c'est-à-dire une chaîne qui peut se lire indifféremment dans les deux sens), comme par exemple « radar » ou « s.o.s ».



Les listes (première approche)

Les chaînes que nous avons abordées à la rubrique précédente constituaient un premier exemple de données composites. On appelle ainsi les structures de données qui sont utilisées pour regrouper de manière structurée des ensembles de valeurs. Vous apprendrez progressivement à utiliser plusieurs autres types de données composites, parmi lesquelles les listes, les tuples et les dictionnaires[21]. Nous n'allons cependant aborder ici que le premier de ces trois types, et ce de façon assez sommaire. Il s'agit-là en effet d'un sujet fort vaste, sur lequel nous devrons revenir à plusieurs reprises.

Sous Python, on peut définir une liste comme une collection d'éléments séparés par des virgules, l'ensemble étant enfermé dans des crochets. Exemple :


>>> jour = ['lundi', 'mardi', 'mercredi', 1800, 20.357, 'jeudi', 'vendredi']
>>> print(jour)
['lundi', 'mardi', 'mercredi', 1800, 20.357, 'jeudi', 'vendredi']

Dans cet exemple, la valeur de la variable jour est une liste.

Comme on peut le constater dans le même exemple, les éléments individuels qui constituent une liste peuvent être de types variés. Dans cet exemple, en effet, les trois premiers éléments sont des chaînes de caractères, le quatrième élément est un entier, le cinquième un réel, etc. (nous verrons plus loin qu'un élément d'une liste peut lui-même être une liste !). À cet égard, le concept de liste est donc assez différent du concept de « tableau » (array) ou de « variable indicée » que l'on rencontre dans d'autres langages de programmation.

Remarquons aussi que, comme les chaînes de caractères, les listes sont des séquences, c'est-à-dire des collections ordonnées d'objets. Les divers éléments qui constituent une liste sont en effet toujours disposés dans le même ordre, et l'on peut donc accéder à chacun d'entre eux individuellement si l'on connaît son index dans la liste. Comme c'était déjà le cas pour les caractères dans une chaîne, il faut cependant retenir que la numérotation de ces index commence à partir de zéro, et non à partir de un.


Exemples :


>>> jour = ['lundi', 'mardi', 'mercredi', 1800, 20.357, 'jeudi', 'vendredi']
>>> print(jour[2])
mercredi
>>> print(jour[4])
20.357


À la différence de ce qui se passe pour les chaînes, qui constituent un type de données non-modifiables (nous aurons plus loin diverses occasions de revenir là-dessus), il est possible de changer les éléments individuels d'une liste :


>>> print(jour)
['lundi', 'mardi', 'mercredi', 1800, 20.357, 'jeudi', 'vendredi']
>>> jour[3] = jour[3] +47
>>> print(jour)
['lundi', 'mardi', 'mercredi', 1847, 20.357, 'jeudi', 'vendredi']

On peut donc remplacer certains éléments d'une liste par d'autres, comme ci-dessous :


>>> jour[3] = 'Juillet'
>>> print(jour)
['lundi', 'mardi', 'mercredi', 'Juillet', 20.357, 'jeudi', 'vendredi']

La fonction intégrée len(), que nous avons déjà rencontrée à propos des chaînes, s'applique aussi aux listes. Elle renvoie le nombre d'éléments présents dans la liste :


>>> print(len(jour))
7

Une autre fonction intégrée permet de supprimer d'une liste un élément quelconque (à partir de son index). Il s'agit de la fonction del() [22] :


>>> del(jour[4])
>>> print(jour)
['lundi', 'mardi', 'mercredi', 'juillet', 'jeudi', 'vendredi']

Il est également tout à fait possible d'ajouter un élément à une liste, mais pour ce faire, il faut considérer que la liste est un objet, dont on va utiliser l'une des méthodes. Les concepts informatiques d'objet et de méthode ne seront expliqués qu'un peu plus loin dans ces notes, mais nous pouvons dès à présent montrer « comment ça marche » dans le cas particulier d'une liste :


>>> jour.append('samedi')
>>> print(jour)
['lundi', 'mardi', 'mercredi', 'juillet', 'jeudi', 'vendredi', 'samedi']
>>>

Dans la première ligne de l’exemple ci-dessus, nous avons appliqué la méthode append() à l’objet jour, avec l’argument ’samedi’. Si l’on se rappelle que le mot append signifie « ajouter » en anglais, on peut comprendre que la méthode append() est une sorte de fonction qui est en quelque manière attachée ou intégrée aux objets du type « liste ». L’argument que l’on utilise avec cette fonction est bien entendu l’élément que l’on veut ajouter à la fin de la liste. Nous verrons plus loin qu'il existe ainsi toute une série de ces méthodes (c'est-à-dire des fonctions intégrées, ou plutôt « encapsulées » dans les objets de type « liste »). Notons simplement au passage que l'on applique une méthode à un objet en reliant les deux à l'aide d'un point. (D'abord le nom de la variable qui référence l'objet, puis le point, puis le nom de la méthode, cette dernière toujours accompagnée d'une paire de parenthèses.)

Comme les chaînes de caractères, les listes seront approfondies plus loin dans ces notes. Nous en savons cependant assez pour commencer à les utiliser dans nos programmes. Veuillez par exemple analyser le petit script ci-dessous et commenter son fonctionnement :


jour = [’dimanche’,’lundi’,’mardi’,’mercredi’,’jeudi’,’vendredi’,’samedi’]
a, b = 0, 0
while a<25 :
a = a + 1
b = a % 7
print(a, jour[b])

La 5e ligne de cet exemple fait usage de l'opérateur « modulo » déjà rencontré précédemment et qui peut rendre de grands services en programmation. On le représente par % dans de nombreux langages (dont Python). Quelle est l'opération effectuée par cet opérateur ?



Exercices

5.11 Soient les listes suivantes :


t1 = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
t2 = [’Janvier’,’Février’,’Mars’,’Avril’,’Mai’,’Juin’,
’Juillet’,’Août’,’Septembre’,’Octobre’,’Novembre’,’Décembre’]

Écrivez un petit programme qui crée une nouvelle liste t3. Celle-ci devra contenir tous les éléments des deux listes en les alternant, de telle manière que chaque nom de mois soit suivi du nombre de jours correspondant :


[' Janvier ' ,31, ' Février ' ,28, ' Mars ' ,31, etc...].

5.12 Écrivez un programme qui affiche « proprement » tous les éléments d'une liste. Si on l'appliquait par exemple à la liste t2 de l'exercice ci-dessus, on devrait obtenir :


Janvier Février Mars Avril Mai Juin Juillet Août Septembre Octobre Novembre Décembre

5.13 Écrivez un programme qui recherche le plus grand élément présent dans une liste donnée. Par exemple, si on l'appliquait à la liste [32, 5, 12, 8, 3, 75, 2, 15], ce programme devrait afficher :


le plus grand élément de cette liste a la valeur 75.

5.14 Écrivez un programme qui analyse un par un tous les éléments d'une liste de nombres (par exemple celle de l'exercice précédent) pour générer deux nouvelles listes. L'une contiendra seulement les nombres pairs de la liste initiale, et l'autre les nombres impairs. Par exemple, si la liste initiale est celle de l'exercice précédent, le programme devra construire une liste pairs qui contiendra [32, 12, 8, 2], et une liste impairs qui </div>


  1. Voir à ce sujet le texte de Eric Steven Raymond : « Comment devenir un hacker », reproduit sur de nombreux sites web, notamment sur : http : //www.secuser.com/dossiers/devenir_hacker.htm, ou encore sur : http : //www.forumdz.comlshowthread.php ? t=4593
  2. Ces logiciels sont appelés des éditeurs de texte. Même s’ils proposent divers automatismes, et sont souvent capables de mettre en évidence certains éléments du texte traité (coloration syntaxique, par ex.), ils ne produisent strictement que du texte non formaté. Ils sont donc assez différents des logiciels de traitement de texte, dont la fonction consiste justement à mettre en page et à ornementer un texte avec des attributs de toute sorte, de manière à le rendre aussi agréable à lire que possible.
  3. bug est à l’origine un terme anglais servant à désigner de petits insectes gênants, tels les punaises. Les premiers ordinateurs fonctionnaient à l’aide de « lampes » radios qui nécessitaient des tensions électriques assez élevées. Il est arrivé à plusieurs reprises que des petits insectes s’introduisent dans cette circuiterie complexe et se fassent électrocuter, leurs cadavres calcinés provoquant alors des court-circuits et donc des pannes incompréhensibles. Le mot français « bogue » a été choisi par homonymie approximative. Il désigne la coque épineuse de la châtaigne.
  4. Sous Windows, vous aurez surtout le choix entre l’environnement IDLE développé par Guido Van Rossum, auquel nous donnons nous-même la préférence, et PythonWin, une interface de développement développée par Mark Hammond. D’autres environnements de travail plus sophistiqués existent aussi, tels l’excellent Boa Constructor par exemple (qui fonctionne de façon très similaire à Delphi), mais nous estimons qu’ils ne conviennent guère aux débutants. Pour tout renseignement complémentaire, veuillez consulter le site Web de Python. Sous Linux, nous préférons personnellement travailler dans une simple fenêtre de terminal pour lancer l’interpréteur Python ou l’exécution des scripts, et faire appel à un éditeur de texte ordinaire tel que Gedit, Kate, ou un peu plus spécialisé comme Geany pour l’édition de ces derniers.
  5. Que peut-on numériser au juste ? Voilà une question très importante, qu’il vous faudra débattre dans votre cours d’informatique générale.
  6. Les noms commençant par une majuscule ne sont pas interdits, mais l'usage veut qu'on le réserve plutôt aux variables qui désignent des classes (le concept de classe sera abordé plus loin dans ces notes). Il arrive aussi que l’on écrive entièrement en majuscules certaines variables que l’on souhaite traiter comme des pseudo-constantes (c’est-à-dire des variables que l’on évite de modifier au cours du programme).
  7. Il faut bien comprendre qu’il ne s’agit en aucune façon d’une égalité, et que l’on aurait très bien pu choisir un autre symbolisme, tel que n ← 7 par exemple, comme on le fait souvent dans certains pseudo-langages servant à décrire des algorithmes, pour bien montrer qu’il s’agit de relier un contenu (la valeur 7) à un contenant (la variable n).
  8. les fonctions seront définies en détail dans les chapitres 6 et 7 (voir page 49).
  9. Tel qu’il est utilisé ici, le terme de séquence désigne donc une série d’instructions qui se suivent. Nous préférerons dans la suite de cet ouvrage réserver ce terme à un concept Python précis, lequel englobe les chaînes de caractères, les tuples et les listes (voir plus loin).
  10. Dans certaines versions de l'éditeur Python pour Windows, le prompt secondaire n'apparaît pas.
  11. Rappel : l'opérateur % est l'opérateur modulo : il calcule le reste d'une division entière. Ainsi par exemple, a % 2 fournit le reste de la division de a par 2.
  12. Ce caractère n’apparaît ni à l’écran, ni sur les listings imprimés. Il est cependant bien présent, à un point tel qu’il fait même problème dans certains cas, parce qu’il n’est pas encodé de la même manière par tous les systèmes d’exploitation. Nous en reparlerons plus loin, à l’occasion de notre étude des fichiers texte (page 119).
  13. … du moins dans cet exemple. Nous verrons un peu plus loin qu’en fait l’exécution continue avec la première instruction qui suit le bloc indenté, et qui fait partie du même bloc que l’instruction while elle-même.
  14. Il serait parfaitement possible d’utiliser un système de traitement de textes, à la condition d’effectuer la sauvegarde sous un format « texte pur » (sans balises de mise en page). Il est cependant préférable d’utiliser un véritable éditeur « intelligent » tel queGedit, Geany ou IDLE, muni d’une fonction de coloration syntaxique pour Python, qui vous aide à éviter les fautes de syntaxe. Avec IDLE, suivez le menu: File → New window (ou tapez CTRL-N) pour ouvrir une nouvelle fenêtre dans laquelle vous écrirez votre script. Pour l’exécuter, il vous suffira (après sauvegarde), de suivre le menu : Edit → Run script (ou de taper CTRL-F5).
  15. Si l'interpréteur Python 3 a été installé sur votre machine comme interpréteur Pythoh par défaut, vous devriez pouvoir aussi entrer tout simplement : python MonScript. Mais attention : si plusieurs versions de Python sont présentes, il se peut que cette commande active plutôt une version antérieure (Python 2.x)
  16. Dans les versions de Python antérieures à la version 3.0, l'encodage par défaut était ASCII. Il fallait donc toujours préciser en début de script les autres encodages (y compris Utf-8).
  17. Voir page 131
  18. La plupart des ordinateurs de bureau actuels contiennent un microprocesseur à registres de 32 bits (même s'il s'agit d'un modèle « dual core ». Les processeurs « 64 bits » seront cependant bientôt monnaie courante.
  19. Les précédentes versions de Python disposaient de deux types d'entiers : « integer » et « long integer », mais la conversion entre ces deux types est devenue automatique dès la version 2.2.
  20. Ceci constitue donc l’une des grandes nouveautés de la version 3 de Python par rapport aux versions précédentes. Dans celles-ci, une donnée de type string était en réalité une séquence d’octets et non une séquence de caractères. Cela ne posait guère de problèmes pour traiter des textes contenant seulement les caractères principaux des langues d’Europe occidentale, car il était possible d’encoder chacun de ces caractères sur un seul octet (en suivant par exemple la norme Latin-1). Cela entraînait cependant de grosses difficultés si l’on voulait rassembler dans un même texte des caractères tirés d’alphabets différents, ou simplement utiliser des alphabets comportant plus de 256 caractères, des symboles mathématiques particuliers, etc. (Vous trouverez davantage d’informations à ce sujet au chapitre 10).
  21. Vous pourrez même créer vos propres types de données composites, lorsque vous aurez assimilé le concept de classe (voir page 169).
  22. Cet ensemble de techniques (qui peuvent aussi s'appliquer aux chaînes de caractères) porte le nom générique de slicing (tranchage). On le met en œuvre en plaçant plusieurs indices au lieu d'un seul entre les crochets que l'on accole au nom de la variable. Ainsi jour[1:3] désigne le sous-ensemble ['mardi', 'mercredi']. Ces techniques un peu particulières sont décrites plus loin (voir pages et suivantes).