Programmation Python/Version imprimable

Un livre de Wikilivres.
Sauter à la navigation Sauter à la recherche
Python.svg
Nuvola-inspired File Icons for MediaWiki-fileicon-ps.png

Ceci est la version imprimable de Programmation Python.

  • Si vous imprimez cette page, choisissez « Aperçu avant impression » dans votre navigateur, ou cliquez sur le lien Version imprimable dans la boîte à outils, vous verrez cette page sans ce message, ni éléments de navigation sur la gauche ou en haut.
  • Cliquez sur Rafraîchir cette page pour obtenir la dernière version du wikilivre.
  • Pour plus d'informations sur les version imprimables, y compris la manière d'obtenir une version PDF, vous pouvez lire l'article Versions imprimables.


Programmation Python

Une version à jour et éditable de ce livre est disponible sur Wikilivres,
une bibliothèque de livres pédagogiques, à l'URL :
https://fr.wikibooks.org/wiki/Programmation_Python

Vous avez la permission de copier, distribuer et/ou modifier ce document selon les termes de la Licence de documentation libre GNU, version 1.2 ou plus récente publiée par la Free Software Foundation ; sans sections inaltérables, sans texte de première page de couverture et sans Texte de dernière page de couverture. Une copie de cette licence est incluse dans l'annexe nommée « Licence de documentation libre GNU ».

Sections

Avant-propos

Grace Hopper, inventeur du compilateur :
« Pour moi, la programmation est plus qu'un art appliqué important. C'est aussi une ambitieuse quête menée dans les tréfonds de la connaissance. »


Choix d'un premier langage de programmation[modifier | modifier le wikicode]

Ce livre est censé vous permettre d'apprendre à programmer à partir du langage Python. Pourquoi Python ? Il existe en effet plusieurs centaines de langages de programmation, chacun avec ses avantages et ses inconvénients. Parmi ces derniers, on compte :

  • Ils sont liés à des environnements de programmation (c'est-à-dire des logiciels) propriétaires.

Cela signifie donc, non seulement que l'institution scolaire désireuse de les utiliser devrait acheter une licence de ces logiciels pour chaque poste de travail (ce qui risque de se révéler assez coûteux), mais surtout que les utilisateurs souhaitant exercer leurs compétences de programmation ailleurs qu'à l'école seraient implicitement forcés d'en acquérir eux aussi des licences.

  • Ce sont des langages spécifiquement liés au seul système d'exploitation Windows. Ils ne sont pas « portables » sur d'autres systèmes (Unix, MacOS, etc.). Cela ne cadre pas avec un projet pédagogique qui ambitionne d'inculquer une formation générale (et donc diversifiée) dans laquelle les invariants de l'informatique seraient autant que possible mis en évidence.

Nous avons alors décidé d'examiner l'offre alternative, c'est-à-dire celle qui est proposée gratuitement dans la mouvance de l'informatique libre (open source). Copiable et modifiable librement au gré de son acquéreur, il est généralement le produit de la collaboration bénévole de centaines de développeurs enthousiastes dispersés dans le monde entier. Son code source étant "épluché" par de très nombreux spécialistes (étudiants et professeurs universitaires), un logiciel libre se caractérise la plupart du temps par un bon niveau de qualité technique. Le plus célèbre des logiciels libres est le système d'exploitation GNU/Linux, dont la popularité ne cesse de s'accroître de jour en jour.

Ce que nous avons trouvé nous a enthousiasmé : non seulement il existe dans le monde de l'open source des interpréteurs et des compilateurs gratuits pour toute une série de langages, mais le véritable cadeau réside dans le fait que ces langages sont modernes, performants, portables (c'est-à-dire utilisables sur différents systèmes d'exploitation tels que Windows, Linux, ou MacOS), et fort bien documentés.

Le langage dominant y est sans conteste C. Ce langage s'impose comme une référence absolue, et tout informaticien sérieux doit s'y frotter tôt ou tard. Il est malheureusement très rébarbatif et compliqué, trop proche de la machine. Sa syntaxe est peu lisible et fort contraignante. La mise au point d'un gros logiciel écrit en langage C est longue et pénible. (Les mêmes remarques valent aussi dans une large mesure pour le langage Java).

Pour nos débuts dans l'étude de la programmation, il nous semble préférable d'utiliser un langage de plus haut niveau, c'est-à-dire plus proche du langage humain que du langage machine, donc plus lisible et moins contraignant.

Après avoir successivement examiné et expérimenté quelque peu les langages Perl et Tcl/Tk , nous avons finalement décidé d'adopter Python, langage très moderne à la popularité grandissante.

La démarche du programmeur[modifier | modifier le wikicode]

Le but de ce cours est de vous apprendre à penser et à réfléchir comme un analyste-programmeur. Ce mode de pensée combine des démarches intellectuelles complexes, similaires à celles qu'accomplissent les mathématiciens, les ingénieurs et les scientifiques.

Comme le mathématicien, l'analyste-programmeur 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 ébauche des hypothèses explicatives, il teste des prédictions.

 l'activité essentielle d'un analyste-programmeur est la résolution de 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.

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.

Un programme n'est rien d'autre qu'une suite d'instructions, encodées en respectant de manière très stricte un ensemble de conventions fixées à l'avance que l'on appelle un langage informatique. La machine est ainsi pourvue d'un mécanisme qui décode ces instructions en associant à chaque « mot » du langage une action précise.

Vous allez donc apprendre à programmer, activité déjà intéressante en elle-même parce qu'elle contribue à développer votre intelligence. Mais vous serez aussi amené à utiliser la programmation pour réaliser des projets concrets, ce qui vous procurera certainement de très grandes satisfactions.

Langage machine, langage de programmation[modifier | modifier le wikicode]

A 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 presqu'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 (voir ci-après). 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, Clarion, Java…). 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 ou, plus « puissantes ». 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 allez apprendre en premier est Python. Il s'agit d'un langage de haut niveau, dont la traduction en codes binaires 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 grosses 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.

Compilation et interprétation[modifier | modifier le wikicode]

Le programme tel que nous l'écrivons à l'aide d'un logiciel éditeur (une sorte de traitement de texte spécialisé) sera appelé désormais programme source (ou code source). Comme déjà signalé plus haut, il existe deux techniques principales pour effectuer la traduction d'un tel programme source en code binaire exécutable par la machine : l'interprétation et la compilation.

  • Dans la technique appelée interprétation, le logiciel interpréteur doit être utilisé chaque fois que l'on veut faire fonctionner le programme. Dans cette technique en effet, chaque ligne du programme source analysé est traduite au fur et à mesure en quelques instructions du langage machine, qui sont ensuite directement exécutées. Aucun programme objet n'est généré.
Apprendre à programmer avec Python 1.png
  • La compilation consiste à traduire la totalité du texte source en une fois. Le logiciel compilateur lit toutes les lignes du programme source et produit une nouvelle suite de codes que l'on appelle programme objet (ou code objet). Celui-ci peut désormais être exécuté indépendamment du compilateur et être conservé tel quel dans un fichier (« fichier exécutable »).
Apprendre à programmer avec Python 2.png

Chacune de ces deux techniques a ses avantages et ses inconvénients :

L'interprétation est idéale lorsque l'on est en phase d'apprentissage du langage, ou en cours d'expérimentation sur un projet. Avec cette technique, on peut en effet tester immédiatement toute modification apportée au programme source, sans passer par une phase de compilation qui demande toujours du temps.

Par contre, lorsqu'un projet comporte des fonctionnalités complexes qui doivent s'exécuter rapidement, la compilation est préférable : il est clair en effet qu'un programme compilé fonctionnera toujours nettement plus vite que son homologue interprété, puisque dans cette technique l'ordinateur n'a plus à (re)traduire chaque instruction en code binaire avant qu'elle puisse être exécutée.

Certains langages modernes tentent de combiner les deux techniques afin de retirer le meilleur de chacune. C'est le cas de Python et aussi de Java. Lorsque vous lui fournissez un programme source, Python commence par le compiler pour produire un code intermédiaire, similaire à un langage machine, que l'on appelle bytecode, lequel sera ensuite transmis à un interpréteur pour l'exécution finale. Du point de vue de l'ordinateur, le bytecode est très facile à interpréter en langage machine. Cette interprétation sera donc beaucoup plus rapide que celle d'un code source.

Apprendre à programmer avec Python 3.png

Les avantages de cette méthode sont appréciables :

  • Le fait de disposer en permanence d'un interpréteur permet de tester immédiatement n'importe quel petit morceau de programme. On pourra donc vérifier le bon fonctionnement de chaque composant d'une application au fur et à mesure de sa construction.
  • L'interprétation du bytecode compilé n'est pas aussi rapide que celle d'un véritable code binaire, mais elle est très satisfaisante pour de très nombreux programmes, y compris graphiques.
  • Le bytecode est portable. Pour qu'un programme Python ou Java puisse s'exécuter sur différentes machines, il suffit de disposer pour chacune d'elles d'un interpréteur adapté.

Tout ceci peut vous paraître un peu compliqué, mais la bonne nouvelle est que tout ceci est pris en charge automatiquement par l'environnement de développement de Python. Il vous suffira d'entrer vos commandes au clavier, de frapper <Enter>, et Python se chargera de les compiler et de les interpréter pour vous.

Mise au point d'un programme - Recherche des erreurs (« debug »)[modifier | modifier le wikicode]

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 France)[1], et l'ensemble des techniques que l'on met en œuvre pour les détecter et les corriger s'appelle debug (ou déboguage).

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[modifier | modifier le wikicode]

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.

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 C++), il vous faudrait recompiler l'intégralité du programme après chaque modification, aussi minime soit-elle.

Erreurs sémantiques[modifier | modifier le wikicode]

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. Il faut analyser ce qui sort de la machine et tâcher de se représenter une par une les opérations qu'elle a effectuées, à la suite de chaque instruction.

Erreurs à l'exécution[modifier | modifier le wikicode]

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 s'est produit (et qui n'avait pas été prévu). Vous rencontrerez davantage ce type d'erreur lorsque vous programmerez des projets de plus en plus volumineux.

Recherche des erreurs et expérimentation[modifier | modifier le wikicode]

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 preuve de beaucoup de perspicacité, persévérance et de patience.

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. Suivant 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 ce livre.

Langages naturels et langages formels[modifier | modifier le wikicode]

Les langages naturels sont ceux que les êtres humains utilisent pour communiquer. Ces langages n'ont pas été mis au point délibérément (encore que certaines instances tâchent d'y mettre un peu d'ordre) : ils évoluent naturellement.

Les langages formels sont des langages développés en vue d'applications spécifiques. Ainsi par exemple, le système de notation utilisé par les mathématiciens est un langage formel particulièrement efficace pour représenter les relations entre nombres et grandeurs diverses. Les chimistes utilisent un langage formel pour représenter la structure des molécules, etc.

 les langages de programmation sont des langages formels qui ont été développés pour décrire des algorithmes et des structures de données. On appelle algorithme la séquence détaillée de toutes les opérations à effectuer pour résoudre un problème

Comme on l'a déjà signalé plus haut, les langages formels sont dotés d'une syntaxe qui obéit à des règles très strictes. Par exemple, 3+3=6 est une représentation mathématique correcte, alors que $3=+6 ne l'est pas. De même, la formule chimique H2O est correcte, mais non Zq3G2.

Les règles de syntaxe s'appliquent non seulement aux symboles du langage (par exemple, le symbole chimique Zq est illégal parce qu'il ne correspond à aucun élément), mais aussi à la manière de les combiner. Ainsi l'équation mathématique 6+=+/5- ne contient que des symboles parfaitement autorisés, mais leur arrangement incorrect ne signifie rien du tout. Lorsque vous lisez une phrase quelconque, vous devez arriver à vous représenter la structure logique de la phrase (même si vous faites cela inconsciemment la plupart du temps). Par exemple, lorsque vous lisez la phrase « la pièce est tombée », vous comprenez que « la pièce » en est le sujet et « est tombée » le verbe. L'analyse vous permet de comprendre la signification, la logique de la phrase (sa sémantique). D'une manière analogue, l'interpréteur Python devra analyser la structure de votre programme source pour en extraire la signification.

Les langages naturels et formels ont donc beaucoup de caractéristiques communes (des symboles, une syntaxe, une sémantique), mais ils présentent aussi des différences très importantes :

Ambiguïté

Les langages naturels sont pleins d'ambiguïtés, que nous pouvons lever dans la plupart des cas en nous aidant du contexte. Par exemple, nous attribuons tout naturellement une signification différente au mot vaisseau, suivant que nous le trouvons dans une phrase qui traite de circulation sanguine ou de navigation à voiles. Dans un langage formel, il ne peut pas y avoir d'ambiguïté. Chaque instruction possède une seule signification, indépendante du contexte.

Redondance

Pour compenser toutes ces ambiguïtés et aussi de nombreuses erreurs ou pertes dans la transmission de l'information, les langages naturels emploient beaucoup la redondance (dans nos phrases, nous répétons plusieurs fois la même chose sous des formes différentes, pour être sûrs de bien nous faire comprendre). Les langages formels sont beaucoup plus concis.

Littéralité

Les langages naturels sont truffés d'images et de métaphores. Si je dis « la pièce est tombée ! » dans un certain contexte, il se peut qu'il ne s'agisse en fait ni d'une véritable pièce, ni de la chute de quoi que ce soit. Dans un langage formel, par contre, les expressions doivent être prises pour ce qu'elles sont, « au pied de la lettre ».

Habitués comme nous le sommes à utiliser des langages naturels, nous avons souvent bien du mal à nous adapter aux règles rigoureuses des langages formels. C'est l'une des difficultés que vous devrez surmonter pour arriver à penser comme un analyste-programmeur efficace.

Pour bien nous faire comprendre, comparons encore différents types de textes :

Un texte poétique

Les mots y sont utilisés autant pour leur musicalité que pour leur signification, et l'effet recherché est surtout émotionnel. Les métaphores et les ambiguïtés y règnent en maîtresses.

Un texte en prose

La signification littérale des mots y est plus importante et les phrases sont structurées de manière à lever les ambiguïtés, mais sans y parvenir toujours complètement. Les redondances sont souvent nécessaires.

Un programme d'ordinateur

La signification du texte est unique et littérale. Elle peut être comprise entièrement par la seule analyse des symboles et de la structure. On peut donc automatiser cette analyse.

Pour conclure, voici quelques suggestions concernant la manière de lire un programme d'ordinateur (ou tout autre texte écrit en langage formel).

Premièrement, gardez à l'esprit que les langages formels sont beaucoup plus denses que les langages naturels, ce qui signifie qu'il faut davantage de temps pour les lire. De plus, la structure y est très importante. Aussi, ce n'est généralement pas une bonne idée que d'essayer de lire un programme d'une traite, du début à la fin. Au lieu de cela, entraînez-vous à analyser le programme dans votre tête, en identifiant les symboles et en interprétant la structure.

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.

Notes[modifier | modifier le wikicode]

  1. 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 ces circuitserie complexes 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.


Introduction

Définition du langage[modifier | modifier le wikicode]

Python est un langage de script de haut niveau, structuré et open source. Il est multi-paradigme et multi-usage.

Développé à l'origine par Guido van Rossum en 1989[1], il est, comme la plupart des applications et outils open source, maintenu par une équipe de développeurs un peu partout dans le monde.

Conçu pour être orienté objet, il n'en dispose pas moins d'outils permettant de se livrer à la programmation fonctionnelle ou impérative ; c'est d'ailleurs une des raisons qui lui vaut son appellation de « langage agile ».

Parmi les autres raisons, citons la rapidité de développement (qualité propre aux langages interprétés), la grande quantité de modules fournis dans la distribution de base ainsi que le nombre d'interfaces disponibles avec des bibliothèques écrites en C, C++ ou Fortran. Il est également apprécié pour la clarté de sa syntaxe, ce qui l'oppose au langage Perl.

Caractéristiques du langage[modifier | modifier le wikicode]

Détaillons un peu les principales caractéristiques de Python, plus précisément, du langage et de ses deux implantations actuelles :

  • Python est portable, non seulement sur les différentes variantes d'Unix, mais aussi sur les OS propriétaires: MacOS, BeOS, NeXTStep, MS-DOS et les différentes variantes de Windows. Un nouveau compilateur, baptisé JPython, est écrit en Java et génère du bytecode Java.
  • Python est gratuit, mais on peut l'utiliser sans restriction dans des projets commerciaux.
  • Python convient aussi bien à des scripts d'une dizaine de lignes qu'à des projets complexes de plusieurs dizaines de milliers de lignes.
  • La syntaxe de Python est très simple et, combinée à des types de données évolués (listes, dictionnaires,...), conduit à des programmes à la fois très compacts et très lisibles. A fonctionnalités égales, un programme Python (abondamment commenté et présenté selon les canons standards) est souvent de 3 à 5 fois plus court qu'un programme C ou C++ (ou même Java) équivalent, ce qui représente en général un temps de développement de 5 à 10 fois plus court et une facilité de maintenance largement accrue.
  • Python gère ses ressources (mémoire, descripteurs de fichiers...) sans intervention du programmeur, par un mécanisme de comptage de références (proche, mais différent, d'un ramasse-miettes).
  • Il n'y a pas de pointeurs explicites en Python.
  • Python est (optionnellement) multi-threadé.
  • Python est orienté-objet. Il supporte l'héritage multiple et la surcharge des opérateurs. Dans son modèle objets, et en reprenant la terminologie de C++, toutes les méthodes sont virtuelles.
  • Python intègre, comme Java ou les versions récentes de C++, un système d'exceptions, qui permettent de simplifier considérablement la gestion des erreurs.
  • Python est dynamique (l'interpréteur peut évaluer des chaînes de caractères représentant des expressions ou des instructions Python), orthogonal (un petit nombre de concepts suffit à engendrer des constructions très riches), réflectif (il supporte la métaprogrammation, par exemple la capacité pour un objet de se rajouter ou de s'enlever des attributs ou des méthodes, ou même de changer de classe en cours d'exécution) et introspectif (un grand nombre d'outils de développement, comme le debugger ou le profiler, sont implantés en Python lui-même).
  • Comme Scheme ou SmallTalk, Python est dynamiquement typé. Tout objet manipulable par le programmeur possède un type bien défini à l'exécution, qui n'a pas besoin d'être déclaré à l'avance.
  • Python possède actuellement deux implémentations. L'une, interprétée, dans laquelle les programmes Python sont compilés en instructions portables, puis exécutés par une machine virtuelle (comme pour Java, avec une différence importante: Java étant statiquement typé, il est beaucoup plus facile d'accélérer l'exécution d'un programme Java que d'un programme Python). L'autre génère directement du bytecode Java.
  • Python est extensible : comme Tcl ou Guile, on peut facilement l'interfacer avec des bibliothèques C existantes. On peut aussi s'en servir comme d'un langage d'extension pour des systèmes logiciels complexes.
  • La bibliothèque standard de Python, et les paquetages contribués, donnent accès à une grande variété de services : chaînes de caractères et expressions régulières, services UNIX standards (fichiers, pipes, signaux, sockets, threads...), protocoles Internet (Web, News, FTP, CGI, HTML…), persistance et bases de données, interfaces graphiques.
  • Python est un langage qui continue à évoluer, soutenu par une communauté d'utilisateurs enthousiastes et responsables, dont la plupart sont des supporters du logiciel libre. Parallèlement à l'interpréteur principal, écrit en C et maintenu par le créateur du langage, un deuxième interpréteur, Jython, écrit en Java, est en cours de développement.
  • Enfin, Python est un langage de choix pour traiter le XML.

Utilisation[modifier | modifier le wikicode]

Comme mentionné plus haut, Python se prête à un grand nombre de tâches. La distribution de base permet, entre autre, des développements réseau, la création d'interfaces graphiques (via tcl/tk), de la programmation cgi, de traiter du XML, etc... Sa relative facilité d'interfaçage avec des bibliothèques écrites en d'autres langages en fait un outil de choix pour des applications de calcul scientifique. Il est également de plus en plus utilisé comme langage de prototypage.

Python est aussi remarquable pour le nombre de bibliothèques accessibles via l'installation des modules appropriés. Que ce soit la connexion avec une base de donnée, l'utilisation de bibliothèques d'interface graphique (wxPython, PyQt, pyGTK), la manipulation avancée de XML (pyXML), le traitement d'image (Python Imaging Library), le développement de jeu vidéo (pygame), OpenGL, la grande majorité des technologies actuelles dispose de son extension python.

Quelques exemples d'utilisation de Python[modifier | modifier le wikicode]

  • Le serveur d'application Zope
  • Administration du moteur de recherche Google
  • Administration des fermes de rendu de la société d'effets spéciaux ILM
  • l'application de dessin vectoriel Skencil (anciennement Sketch)
  • Boa constructor, outil de développement rapide d'applications wxPython

D'autres exemples sont disponibles sur Python success stories (anglais)

Version 2 et version 3[modifier | modifier le wikicode]

Il est à noter que les deux principales familles de python sont la famille version 2 et la famille version 3.

Lorsqu'il est nécessaire de modifier des anciens code, ou d'utiliser des anciennes librairies, il peut être utile d'apprendre la version 2.

Mais la version 3 devant à terme remplacer la version 2, il peut être d'ores et déjà utile de commencer à apprendre la version 3.

Références[modifier | modifier le wikicode]


Installation

Exécution sans installation[modifier | modifier le wikicode]

Certains sites tels que http://pythonfiddle.com/ permettent d'exécuter du code Python sur un serveur distant, sans avoir à l'installer chez soi. Toutefois pour développer des applications dignes de ce nom, il convient de l'avoir à disposition sur sa machine.

Installation locale[modifier | modifier le wikicode]

Il est possible d'installer Python sur la plupart des systèmes d'exploitation en le téléchargeant sur http://www.python.org/download.

Si vous n'avez pas les droits d'administrateurs de votre machine, il existe aussi une version portable sur http://www.portablepython.com.

Pour les systèmes Windows, vous pouvez télécharger le fichier MSI. Python est le plus souvent automatiquement installé avec la plupart des distribution Linux ou Mac OS, mais il est recommandé (nécessaire) de télécharger une version actualisée :

Linux[modifier | modifier le wikicode]

Vous êtes probablement chanceux et l'interpréteur Python est déjà installé sur votre machine. pour le tester, tapez python3 dans un terminal. Si vous voyez quelque chose comme dans la prochaine section, vous êtes bon.

Si vous devez installer Python, essayez d'abord d'utiliser le gestionnaire de paquet de votre système d'exploitation ou allez visiter le dépôt où ces paquets sont disponibles, et récupérez Python 3. Python 3.0 est sorti en décembre 2008 ; toutes les distributions (BSD, GNU/Linux-Hurd-Linux Libre)devraient avoir Python 3 disponible, donc vous ne devriez pas avoir besoin de compiler Python 3 "from scratch" après avoir téléchargé le code source. Debian et Fedora possèdent des paquets binaires Python3 disponibles, mais ne le sont pas encore pas défaut, il faudra donc les installer par vous-même.

Voici donc les étapes pour compiler Python sur une unixerie (GNU/Linux, BSD...) :

$ tar -xJvf Python-3.3.3.tar.xz
... liste des fichiers décompressés 
  • Déplacez-vous dans le dossier nouvellement créé et dîtes à votre système de compiler et installer le programme
$ cd Python-3.3.3/
$ ./configure
 ... plein de messages, prêtez attention aux erreurs ... 
$ make
 ... encore plus de messages... 
$ make install

Les commandes ci-dessus installeront Python 3 dans votre dossier /usr/local. Si vous voulez utiliser IDLE, vous devez vous assurer que tk et tcl ainsi que leurs fichiers de développement sont installés sur le système. Vous verrez des avertissements durant la phase de compilation (make) si ces derniers ne sont pas disponibles.

Variable d'environnement :

Exécuter un script python

 > set PATH=%PATH%;C:\<Repertoire de python>
 > python MonScript.py

Utilisateurs de Mac[modifier | modifier le wikicode]

Depuis Mac OS X (Tiger), Python est embarqué par défaut avec l'OS, mais vous devrez mettre à jour vers Python 3 de la manière décrite ci-dessus, jusqu'à ce qu'OS X incluse Python 3 (vérifiez la version en tapant python3 dans un terminal).

 depuis l'apparition de la version 2.3, il est vivement recommandé aux francophones que nous sommes d'inclure l'un des pseudo-commentaires suivant au début de tous nos scripts Python (à la 1e ou 2e ligne) :
# -*- coding:Latin-1 -*-

Ou encore mieux :

 # -*- coding:Utf-8 -*-

Mode Interactif[modifier | modifier le wikicode]

IDLE sous KDE
IDLE 0.8 sous Windows 2000
IDLE sous Windows 7

Python dispose d'une interface interactive appelée IDLE, qui permet de tester les commandes de base. Pour appeler l'interface, il suffit de saisir python3 en ligne de commande sur macOS et Linux ou ouvrir l'application "IDLE (Python GUI)" sous Windows. Voici par exemple ce qui apparaît dans une fenêtre de terminal KDE (sous Linux)[1] :

$ python3
Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print("Hello World")
Hello World
>>> exit()
$

Les trois caractères « >>> » constituent le signal d'invite, ou prompt principal, lequel vous indique que Python est prêt à exécuter une commande. En mode interactif, ce que vous tapez est immédiatement exécuté. Mais le plus employé par les programmeurs est d'exécuter un script Python contenant plusieurs instructions, en lançant un fichier .py sauvegardé sur le disque dur.

Calculer avec Python[modifier | modifier le wikicode]

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 :

>>> 5+3            # 8

>>> 2 - 9          # -7 : les espaces sont optionnels

>>> 7 + 3 * 4      # 19 : la hiérarchie des opérations mathématiques est bien respectée
>>> (7+3)*4        # 40

>>> 20 / 3         # 6 : arrondi

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 sont fonctionnelles.

Par défaut, la division est cependant une division entière, ce qui signifie que si on lui fournit des arguments qui sont des nombres entiers, le résultat de la division est lui-même un entier (tronqué, mais dans les versions de python 3.* la division n'est plus tronquée : 5/2 donne bien 2.5), comme dans le dernier exemple ci-dessus. Si vous voulez qu'un argument soit compris par Python comme étant un nombre réel, il faut le lui faire savoir, en fournissant au moins un point décimal[2].

Essayez par exemple :

>>> 20.0 / 3 # (comparez le résultat avec celui obtenu à l'exercice précédent)

>>> 8./5

Si une opération est effectuée avec des arguments de types mélangés (entiers et réels), Python convertit automatiquement les opérandes en réels avant d'effectuer l'opération.
Essayez :

>>> 4 * 2.5 / 3.3

Aide[modifier | modifier le wikicode]

Lorsque vous souhaitez obtenir de l'aide sur une fonction ou une librairie, il suffit d'utiliser la commande « help » dans l'interpréteur interactif. Pour savoir comment fonctionnent les expressions régulières sous python par exemple, exécutez

Obtenir de l'aide sur une librairie python

 > import re
 > help(re)

pip[modifier | modifier le wikicode]

pip est le gestionnaire de paquets fourni avec Python. Pour l'utiliser :

pip install nom-du-paquet

Références[modifier | modifier le wikicode]

  1. 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 l'environnement graphique WindowMaker (plutôt que KDE ou Gnome trop gourmands en ressources), en ouvrant une simple fenêtre de terminal pour lancer l'interpréteur Python ou l'exécution des scripts, et en faisant appel à un logiciel tel que Nedit ou SciTE pour l'édition de ces derniers.
  2. Dans les langages de programmation, les notations numériques de base sont souvent celles des pays anglophones : le séparateur décimal est le point, et non une virgule comme en français. Dans le monde de l'informatique, les nombres réels sont souvent désignés comme des nombres "à virgule flottante", ou encore des nombres « de type float ».


Éditeurs

Utilité des éditeurs[modifier | modifier le wikicode]

Si le mode interactif 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 écrites disparaissent irrémédiablement après fermeture de l'interpréteur. Il convient donc de sauvegarder les programmes dans des fichiers, sur une mémoire morte, de manière à pouvoir les retravailler par étapes successives, les transférer sur d'autres machines, etc.

Pour ce faire, il est déconseillé d'utiliser de simples éditeurs de texte tels que Edit, Notepad ou WordPad, car ils ne sont pas ANSI "intelligent", ni muni de la fonction de coloration syntaxique du code source pour Python, qui aide à relire rapidement et éviter les fautes de syntaxe.

Par conséquent, il vaut mieux en utiliser des spécialisés en programmation, appelés environnement de développement (EDI). Par exemple :

  • SciTE
  • DrPython
  • Eclipse
  • NetBeans[1]
  • NEdit
  • PythonWin[2]
  • Python scripter[3] : auto-complétion, navigation entre classe avec 'CTRL', génération et exécution des tests unitaires, debugger...
NEdit sous Gnome (Linux).

SciTE[modifier | modifier le wikicode]

SciTE (acronyme de Scintilla Text Editor) est un logiciel éditeur de texte graphique, gratuit et open source fonctionnant sous les environnements Linux et Windows. Il est capable d'effectuer la coloration syntaxique, l'auto-complétion et surtout le pliage de code (code folding), c'est à dire le masquage à volonté de différents blocs d'instructions (contenu d'une classe, d'une fonction, d'une boucle, etc.) : cette fonctionnalité se révèle extrêmement pratique lorsque vos scripts commencent à s'allonger... Il intègre également une fenêtre de terminal ainsi qu'un raccourci pour lancement des scripts.

Cet éditeur est disponible pour Windows et pour Linux sur http://www.scintilla.org/SciTE.html.

Scintilla étant une plateforme d'édition de texte qui propose par exemple des outils spécifiques pour corriger du code écrit avec SciTE. Ces deux logiciels sont principalement l'œuvre de leur créateur Neil Hodgson, qui les a placés sous une licence libre peu connue, l'Historical Permission Notice and Disclaimer.

Langages supportés[modifier | modifier le wikicode]

Les langages compris par SciTE. Il est actuellement capable d'appliquer une syntaxe de style à ces langages :

Les langages marqués par un astérisque doivent être vérifié pour marcher pour un nombre important de personne.

Installation sous Linux[modifier | modifier le wikicode]

L'éditeur Scintilla fait dorénavant partie des paquetages fournis d'office avec les distributions récentes de Linux. Sinon, téléchargez-le au départ du site web mentionné ci-dessus. Sinon :

  • téléchargez l'archive gscite***.tgz puis l'extraire avec tar ;
  • installez l'exécutable SciTE dans /usr/local/bin ;
  • installez tout le reste (fichiers *.properties) dans /usr/share/scite (et non /usr/share/gscite !).

Installation sous Windows[modifier | modifier le wikicode]

  • Téléchargez l'archive wscite***.zip puis l'extraire dans \Program files ;
  • installez une icône de lancement pour l'exécutable SciTe.exe.

Pour les deux versions[modifier | modifier le wikicode]

On peut personnaliser beaucoup de choses (polices, etc.) en éditant le fichier des propriétés globales (Menu Options → Open global options file).

Par exemple, pour activer de jolis symboles pour replier/déplier, dans la marge de gauche :

  • fold.symbols = 2 # pour de belles icônes + et - cerclées
  • fold.on.open = 1 # ainsi tout est plié au départ
  • margin.width =0 # pour supprimer la marge inutile

Pour forcer le remplacement automatique des tabulations par des groupes de 4 espaces :

  • tabsize = 4
  • indent.size = 4
  • use.tabs = 0

Traductions[modifier | modifier le wikicode]

La traduction doit être téléchargée[4], renommée en "locale.properties" et déplacée dans le même répertoire que les propriétés globales.

Il faut donc passer en root :

sudo nautilus

et aller dans le répertoire par défaut :

/usr/share/scite

Utilisation[modifier | modifier le wikicode]

Scite.png


DrPython[modifier | modifier le wikicode]

DrPython est un environnement d'exploration pour le langage Python. (Il y a des autres logiciels comme ça pour les autres langues, par exemple DrJava et DrScheme.) DrPython est un logiciel Python, donc il faut installer Python d'abord.

Téléchargez les suivantes :

- Python soi-même : du site web Python. L'installeur est disponible en cliquant "Windows installer", ou ici pour Python 2.7.

- La version du bibliothèque wxPython correspondant à la version de Python -- ça veut dire wxPython pour Python 2.7. En générale, c'est ici.

- DrPython; télécharger seulement le paquet du site Sourceforge ici.

Maintenant il faut installer Python et wxPython. Pour le faire, double-cliquez sur les fichiers vous avez téléchargé, commençant avec python-2.7.msi. Les installations sont en anglais. Il suffit de cliquer sur «Next» plusieurs fois, mais je vais aussi essayer de traduire les écrans.

Python 2.7
Anglais Français
Select whether to install Python 2.7 for all users of this computer. Install for all users/Install for just me (not available on Windows Vista) Choisissez à installer Python 2.7 pour tout utilisateur du ordinateur. Installer pour tout utilisateur/Installer pour seulement moi (pas disponible sur Windows Vista) [Le défaut, «Installer pour tout utilisateur», est probablement le plus facile.]
Select destination directory. Please select a directory for the Python 2.7 files. Choisissez dossier destination. Veuillez sélectionner un dossier pour les fichiers de Python 2.7. [Le défaut est bien.]
Customize Python 2.7. Select the way you want features to be installed. Customizez Python 2.7. Choisissez la façon d'installer les traits que vous préférez. [Le defaut est d'installer tout trait, qui est acceptable.]
Please wait while the installer installs Python 2.7. This may take several minutes. Veuillez patienter pendant que l'installeur installe Python 2.7. Ça peut prendre plusieurs minutes.
Completing the Python 2.7 installer. Special thanks to Mark Hammond, without whose years of freely shared Windows experience, Python for Windows would still be Python for DOS. Click the Finish button to exit the installer. Termine l'installeur Python 2.7. Remerciements spéciale à Mark Hammond, sans les années d'experience duquel Python pour Windows serait toujours Python pour DOS. Cliquez sur «Finish» pour quitter l'installeur.


Après vous avez fait ça, vous allez voir dans le menu Démarrer un groupe qui s'appelle Python 2.7, et dedans vous allez voir «IDLE (Python GUI)», «Module Docs», «Python (command line)» («Invite des commandes Python»), «Python Manuals», et «Uninstall Python» («Déinstaller Python»). Ç'est bien, mais on va continuer avec la bibliothèque wxPython.

wxPython 2.8
Anglais Français
Welcome to the wxPython2.8-unicode-py27 Setup Wizard. This will install wxPython 2.8.11.0 (unicode) for Python 2.7 on your computer. It is recommended that you close all other applications before continuing. Click Next to continue, or Cancel to exit Setup. Bienvenue à installeur wxPython2.8-unicode-py27. Ça va installer wxPython 2.8.11.0 (unicode) pour Python 2.7 sur votre ordinateur. C'est conseillé que vous fermez toute autre application avant de continuer. Cliquez «Next» pour continuer, ou «Cancel» pour quitter l'installeur. [Le plupart de celui-ci est commun dans les installeurs.]
License agreement. (The full wxWindows library license.) I accept the agreement./I do not accept the agreement. Accord de la licence [Ceux qui suit est le texte complet de la licence de la bibliothèque wxWindows.] J'accepte la licence./Je n'accepte pas la licence. [On peut accepter ; la licence est très douce.]
Select destination location. Where should wxPython be installed? Choisissez location destination. Où devrait wxPython être installe ? [Le défaut est le meilleur lieu.]
Select components. Which components should be installed? Choisissez composants. Quels composants devrait être installé ? [Il y a seulement un composant, qu'il faut installer. Alors, le défaut et parfait.]
Installing. Please wait while Setup installs wxPython2.8-unicode-py27 on your computer. Veuillez patienter pendant que l'installeur installe wxPython2.8-unicode-py27 sur votre ordinateur.
Completing the wxPython Setup Wizard. Setup has finished installing wxPython on your computer. Click Finish to install Setup. View README win32.txt./Compile Python .py files to .pyc./Create batch files for tool scripts. Termine l'installeur wxPython. L'installer a fini à installer wxPython sur votre ordinateur. Cliquez «Finish» pour quitter. Afficher README win32.txt./Compiler les fichiers Python .py à .pyc./Crèer fichiers pour [....]. [Décocher la première case, parce que c'est un fichier anglais, mais les autres sont utile.]


Après ça, vous allez voir une fenêtre noire qui va afficher un peu de texte et se ferme.

Maintenant, dépaquetez le dernier fichier que vous avez téléchargé : DrPython_3.11.3.zip. Vous allez trouver dedans un dossier avec beaucoup de fichiers. Cherchez un qui s'appelle drpython. (Il y aura au moins deux.) Double-cliquez le. Après ça vous allez voir une fenêtre qui paraît un peu comme cela :

Drpython-Screenshot-Empty

Félicitations ! Vous avez réussit à installer DrPython.

N.B. Il doit avoir une façon d'installer DrPython pour qu'on puisse l'ouvrir plus facilement, par exemple en créant un raccourci, mais je n'ai pas encoure trouvé.

Eclipse[modifier | modifier le wikicode]

Installation de Eclipse[modifier | modifier le wikicode]

Eclipse est un environnement de développement intégré (EDI), générique et extensible (site officiel http://www.eclipse.org).

Initialement prévu pour développer en Java, il peut maintenant également gérer des projets développés avec d'autres langages de programmation tels que :

  • Le C et le C++ grâce à l'ensemble de plugins CDT[5] (compilateur non intégré).
  • Le Python via PyDev[6].

La page de téléchargement d'Eclipse permet de récupérer une version déjà adaptée au langage ciblé sur http://www.eclipse.org/downloads/. Mais pour installer un plugin manuellement, il faut :

  • Lancer Eclipse, puis dans le menu déroulant :Help>Software Updates>Find and Install...
  • Cocher Search for new features to install, bouton Next. Bouton New Remote Site..., entrer l'adresse de téléchargement :
Name: Nom du plugin
URL: adresse du plugin, ex : http://www.eclipse.org/cdt/downloads.php
  • Bouton Finish, choisir un miroir proche puis continuer l'installation.

Utilisation de Eclipse[modifier | modifier le wikicode]

Eclipse


PyDev[modifier | modifier le wikicode]

PyDev est un plugin Eclipse pour le développement d'un projet Python (et Jython).

Il a été créé en Juillet 2003 par Aleks Totic et est maintenu depuis Octobre 2004 par Fabio Zadrozny. Il propose entre autres les fonctionnalités suivantes :

  • complétion de code,
  • analyse et mise en évidence de la syntaxe,
  • debug
  • ...

Installation du plugin PyDev[modifier | modifier le wikicode]

Sous Eclipse, voici la procédure à suivre pour installer le plugin :

  • Menu "Help" / "Software Updates" / "Find and install ..." / "Search for new feature to install"
  • "New Remote Site..." / Name : Python Dev, URL : http://pydev.org/updates/ / Finish

Une fois le plug-in installé, il faut configurer le compilateur Python :

  • Menu "Window" / "Preferences" / "PyDev" + "Interpreter Python" / "New"

Il vous faudra ensuite choisir l'exécutable python : "/usr/bin/python" sous Linux, "C:\Python\python.exe" sous Windows et valider, puis sélectionner les répertoires à inclure dans le PYTHONPATH (en cas de doute, prenez ceux qui vous sont proposés).

Créer un projet "Hoo hoo World" avec le plugin PyDev[modifier | modifier le wikicode]

Sous Eclipse, une fois le plug-in installé, choisir de créer un nouveau projet

  • Menu "File" / "New" / "Project"
  • Sélectionner Pydev Project / "Next"
  • Donner un nom et choisir la version correspondant à python (ex: 2.4).
  • Valider ("Finish") : Vous devez avoir une nouvelle entrée correspondant au projet
  • Clic droit sur le projet pour ajouter un nouveau module ("New" / "Pydev module")
  • donner lui un nom (ex: monScript)
  • saisir le code suivant dans le fichier :
print("Hoo hoo World")
  • sauvegarder (CTRL + S, ou clic sur la disquette, ou menu "File" / "Save")
  • exécuter : Bouton droit sur le fichier monScript / "Run as" / "Python run"
Pour les prochaines exécutions du script, utiliser la barre d'outil (symbole lecture blanc dans un rond vert) ou CTRL + F11.

Complétion auto[modifier | modifier le wikicode]

Pour voir la complétion automatique de code, utilisez CTRL + Espace.

Par exemple pour le code suivant :

x = "Bonjour"
x.

si l'on place le curseur après le point, et que l'on tape CTRL + Espace, l'ensemble des méthodes de la classe String seront proposées (ex: .upper() qui passe en majuscule la chaîne de caractère x).

Lancement des scripts[modifier | modifier le wikicode]

Certains EDI permettent de lancer les scripts en cliquant. Toutefois d'une manière générale, il faut les exécuter en lançant en ligne de commande l'interpréteur Python, en lui fournissant comme premier argument le nom du fichier qui contient le script, voire des paramètres supplémentaires comme autres arguments.

Par exemple, si vous avez placé un script dans un fichier nommé MonScript.py, il suffira d'entrer la commande suivante dans une fenêtre de terminal (ou une invite de commande sous Windows) pour que ce script s'exécute :

python3 MonScript.py (utiliser "python" à la place de "python3" sous Windows)

ou

python3 MonScript.py argument2 argument3

Par ailleurs, quand le fichier porte bien l'extension conventionnelle Python (.py), il a un icône Python et il est possible de l'exécuter simplement en cliquant sur son nom ou sur l'icône correspondante dans le gestionnaire de fichiers (c'est-à-dire l'explorateur, sous Windows, Gnome, ou Konqueror, sous KDE). En effet ces gestionnaires graphiques « savent » 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.

Évitez cependant de choisir des noms qui risqueraient d'être déjà attribués à des modules python existants, tels que "math.py" ou "Tkinter.py".

Si vous travaillez avec IDLE sous Windows, vous pouvez lancer l'exécution du script en cours d'édition, directement à l'aide de la combinaison de touches <Ctrl-F5>.

En-tête des fichiers[modifier | modifier le wikicode]

Enfin, l'en-tête des fichiers .py doit toujours contenir le shebang :

#!/usr/bin/python3

et avec Python 2 leur encodage, comme :

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

ou

# -*- coding:Utf-8 -*-

Ces pseudo-commentaires indiquent à Python que vous utiliserez dans votre script :

  • Soit le jeu de caractères accentués correspondant aux principales langues de l'Europe occidentale (Français, Italien, Portugais, etc.), codé sur un seul octet suivant la norme ISO-8859 ;
  • Soit le système de codage mondial sur deux octets appelé Unicode (dont la variante Utf-8 ne code que les caractères « spéciaux » sur deux octets, les caractères du jeu ASCII standard restant codés sur un seul octet). Ce dernier système commence à se répandre de plus en plus, car il présente l'avantage de permettre la coexistence de caractères de toutes origines dans le même document (caractères grecs, arabes, cyrilliques, japonais, etc.). C'est ce mode qu'il faut privilégier pour plus de compatibilité.

Python peut utiliser les deux systèmes, mais vous devez lui signaler lequel vous utilisez. Si votre système d'exploitation est configuré de telle manière que les frappes clavier génèrent des codes Utf-8, configurez votre éditeur de textes pour qu'il utilise lui aussi ce codage, et placez le second des pseudo-commentaires indiqués ci-dessus au début de chacun de vos scripts. Mac OS X et Linux utilisent ce codage.

Si votre système d'exploitation fonctionne suivant la norme ancienne (ISO-8859), vous devrez utiliser plutôt le premier pseudo-commentaire. C'est le cas de Windows.

Si vous n'en indiquez aucun, vous recevrez de temps à autre des messages d'avertissement de la part de l'interpréteur, et vous éprouverez peut-être même quelques difficultés à éditer correctement vos scripts dans l'environnement IDLE (en particulier sous Windows).

Sous Python 3 ces problèmes d'encodage n’apparaissent pas car celui-ci utilise par défaut l'Unicode.

Références[modifier | modifier le wikicode]


Programmer en deux minutes

1. Ouvrir Python (command line). Comment ? En exécutant python ou en recherchant python.exe

Une invite de commande s'affiche.

2. Saisissez « a=3 » puis pressez Entrée/Retour. Dans l'invite suivante saisissez « print(a) ». Vous avez à l'écran :

>>> a=3
>>> print(a)
3

3. Saisissez ces commandes :

>>> a=0                         # Shift + Enter pour sauter à la ligne suivante
>>> while (a<4):                # ouvre un process (1), donc...
...     a = a+1  # ajouter une indentation (espace) au début pour signifier l'appartenance au process 1.
...     print("semaine"), a   # demande d'afficher "semaine" et a.
... 
semaine 1                         # 1er résultat
semaine 2
semaine 3
semaine 4                         # etc, votre programme s'exécute en boucle tant que a<4   

4. Ouvrez un éditeur de texte, écrivez...

a = 0
while (a<20):
	a = a + 1
	print ("semaine"), a, "2009"

...et enregistrez ce script sous la forme *.py

5. Ouvrez la ligne de commande de votre système d'exploitation (par exemple : bash GNU/Linux, Terminal pour Mac OS X, ou cmd pour Windows), placez votre invite de commande dans le répertoire de votre fichier *.py, affichez votre fichier *.py dans votre invite de commande et exécutez-le en pressant Enter.


Félicitation, vous avez écrit et exécuté votre premier script !



Programmer en deux minutes/une messagerie instantanée

Nous allons écrire deux scripts en Python et les exécuter chacun dans une console. Les deux programmes vont communiquer afin d'envoyer un message et d'attendre la réponse.

Écoute[modifier | modifier le wikicode]

1). Ouvrir un éditeur de texte, et coller le script suivant (sans caractère spéciaux comme "é")...

...enregistrez ce script (par exemple ecoute.py) et exécutez-le.

Discussion[modifier | modifier le wikicode]

2. Ouvrir l'éditeur de texte, écrire le script de discussion...

...enregistrez ce script (par exemple discussion.py) et exécutez-le dans une nouvelle console.


Félicitation, vos deux consoles communiquent !



Programmer en deux minutes/l'interface de Wikipédia pour programmer

Nous allons écrire un script en Python et l'exécuter dans une console. Le script va utiliser deux ensembles de commandes définis dans la bibliothèque fournie à l'installation du langage.

L'interface avec Wikipédia se fait via des requêtes à :

https://fr.wikipedia.org/w/api.php?

Par exemple :

https://fr.wikipedia.org/w/api.php?action=query&prop=info%7Crevisions&titles=Accueil

Dernier réviseur de la page[modifier | modifier le wikicode]

1. Ouvrir un éditeur de texte, coller le script suivant (sans caractère spéciaux comme "é" si le fichier est en ASCII au lieu de Unicode)...

...enregistrez ce script (par exemple reviseur_de_la_page.py) et exécutez-le. Le script utilise cette requête pour afficher le dernier réviseur de la page d'accueil.


Note : il s'agit de la méthode utilisant les bibliothèques natives de Python. Une alternative est d'utiliser le framework Pywikibot, qui s'occupe de l'API de MediaWiki à la place du développeur, rendant la tâche beaucoup plus simple pour des scripts plus perfectionnés.

Boucle réviseur bistro[modifier | modifier le wikicode]

2. Obtenir la liste des derniers réviseurs des Bistros du mois dernier. Ouvrir l'éditeur de texte, écrire ce script utilisant plusieurs fois cette requête... Si vous souhaitez utiliser le code suivant avec Python 3, faites les mêmes modifications que dans le script précédent. C'est-à-dire : rajoutez des parenthèses aux print ; chargez la classe urllib.request (au lieu d'urllib tout court) ; utilisez la fonction urllib.request.urlopen (au lieu de urllib.urlopen) ; transformez le résultat de read en chaîne de caractères (infos = str(url.read(), 'utf_8')).

...enregistrez ce script (par exemple boucle_reviseur_bistro.py) et exécutez-le.

Tous les réviseurs de la page[modifier | modifier le wikicode]

3. La liste des réviseurs de la page d'accueil entre deux dates, et les commentaires de révisions : ouvrir l'éditeur de texte, écrire ce script, faire les mêmes modifications pour Python 3 le cas échéant... Ce script utilise cette requête.

Félicitations, vous utilisez Wikipédia via son API !


Vous pouvez poursuivre cet exercice en programmant du python sur une base vierge, ou alors utiliser la librairie d'instructions Pywikipedia et les scripts Pywikipedia hébergés par Wikimédia. Par exemple, vous devriez être capable de lire un script tel que :

Le script statistics_in_wikitable.py importe quelques librairies d'instructions dont Pywikipedia, définit trois variables, définit l'objet StatisticsBot, puis définit une fonction principale qui est exécutée à la fin du script (par l'instruction try: main(your_page)).



Programmer en deux minutes/un serveur Web

Nous allons écrire un script en Python et l'exécuter dans une console. Le programme va utiliser deux ensemble d'instructions, ces ensembles étant définis dans la bibliothèque de base.

Serveur HTTP[modifier | modifier le wikicode]

1. Ouvrir un éditeur de texte, écrire le script...

...enregistrez ce script (par exemple serveur_http.py) dans un répertoire que vous voulez partager (par exemple /PUBLIC_web) et exécutez-le dans une console.

Félicitation, votre programme répond aux requêtes http://localhost:5432 [Note 1] et votre répertoire public[Note 2] peut être téléchargé.

  1. « http://localhost:5432 » est une requête de protocole HTTP à votre machine locale via le port 5432
  2. Nommé « /PUBLIC_web » dans l'exemple

Index.html[modifier | modifier le wikicode]

2. Ouvrez un éditeur de texte et créez l'index de votre site statique :

...enregistrez ce fichier sous le nom index.html dans le répertoire que vous partagez (Nommé « /PUBLIC_web » dans cet exemple).


Félicitation, votre programme répond aux requêtes http://localhost:5432 en servant l'index de votre site web !



Afficher un texte

Ce chapitre détaille les différentes manières d'afficher un texte en console, par exemple pour générer des logs. Les interfaces graphiques plus élaborées seront traitées avec des bibliothèques.

print()[modifier | modifier le wikicode]

La fonction print sert à afficher des données sur la sortie standard, qui est l’écran. Exemple :

fonction print
>>> print('Hello World!')
Hello World!

print formaté[modifier | modifier le wikicode]

Il est possible de changer une partie du texte en y incorporant des marqueurs de conversion précédés de l'opérateur "%". Il s'agit alors d'un "print formaté" (comme avec printf dans d'autres langages).

Les paramètres placés entre parenthèses à droite de la chaine à afficher seront insérés dedans, en lieu et place des marqueurs. Cette technique a l'avantage de convertir automatiquement les variables pour qu'elles s'inscrivent dans le texte et qu'elles s'affichent.

Parmi les marqueurs disponibles[1], on trouve :

  • %s représente un paramètre de type "string" (texte).
  • %d un "digit" (nombre entier).
  • %f un "floating" (flottant : nombre réel).

Exemple :

>>> int1, int2 = 1, 2

>>> print(u"le résultat de " + int1 + ' + ' + int2 + " est : " + int1 - int2)
  et le résultat de 1 + 2 est 3

>>> print(u"le résultat de", int1 , '+', int2, "est :", int1 - int2)
  et le résultat de 1 + 2 est 3

>>> print(u"et le résultat de %s + %d est %f" % (int1, int2, int1 + int2))
  et le résultat de 1 + 2 est 3.000000

input()[modifier | modifier le wikicode]

la fonction input() fait comme la fonction print(), mais stoppe le programme en attente que l'utilisateur presse "entrée". Son résultat sera de type 'string' (chaine de caractère, texte).

Ici le contenu de ce que l'utilisateur a tapé avant de valider sera stocké dans la variable nommée variable.

>>> variable = input('Quel est votre nom ? ')
Quel est votre nom ? Pierre Henry FAGAN
>>> type(variable)
<class 'str'>
>>> print('Bonjour ' + variable)
Bonjour Pierre Henry FAGAN

raw_input()[modifier | modifier le wikicode]

raw_input() fait comme input(), mais renvoie toujours une chaine de caractère. Elle ne plante pas si le texte est vide.

Attention !
link={{{link}}}

A partir de Python 3.1, la fonction "raw_input()" n'existe plus, et la fonction input() la remplace et renvoie systématiquement une chaine de caractères.

Afficher des caractères spéciaux[modifier | modifier le wikicode]

Normalement, les symboles ne faisant pas partie du code ASCII sont traités comme les autres. Ex :

print('à â ç é è ê ë ï ô ù ÿ')
à â ç é è ê ë ï ô ù ÿ

Toutefois selon l'encodage, il peut être nécessaire de les convertir en Unicode en plaçant un "u" avant :

print(u'à â ç é è ê ë ï ô ù ÿ')

Pour les retours à la ligne, utiliser "\n".

Antislash[modifier | modifier le wikicode]

Les caractères affichés par les fonctions précédentes doivent être encadrés par des apostrophes ou des guillemets, mais que se passe-t-il s'ils contiennent eux-mêmes ces symboles ?

Testons la fonction print  :

ce qui marche :
>>> print("ça marche aussi")
ça marche aussi
>>> print('et ça ? "ça marche" ou pas')
et ça ? "ça marche" ou pas
>>> print("et on 'essaye' l'inverse")
et on 'essaye' l'inverse
ce qui ne marche pas :
>>> print('un simple guillemet ' encadré par du simple quote ')
[message d'erreur]
>>> print(" pareil pour le " double ")
[message d'erreur]
>>> print("double " deux " fois dans double")
[message d'erreur]

En Python, le simple quote peut encadrer le double, et le double peut encadrer le simple, car la chaîne commence au premier guillemet et finit au même guillemet.


Pour s'affranchir de ces limitations, on utilise un caractère d'échappement, qui est, en Python, l'antislash (« \ »). Il permet quelques subtilités complémentaires :

  • En premier lieu, il permet d'écrire sur plusieurs lignes n'importe quel type de commande. Pratique pour éviter de dépasser les 120 caractères pouvant nécessiter l'utilisation d'un ascenseur latéral pour être lus.
  • À 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 :
>>> print('une chaîne avec des \' guillemets \' simples dans des simples, c\'est protégé ')
une chaîne avec des ' guillemets ' simples dans des simples, c'est protégé

>>> 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.

On remarque que la séquence \' permet d'insérer une apostrophe dans une chaîne délimitée par des apostrophes, et \" par des guillemets. De même, "\\" affiche "\".

D'autres caractères peuvent aussi être introduits par antislash :

  • Retour chariot : \n
  • Tabulation : \t

Triple quotes[modifier | modifier le wikicode]

Si le nombre d’antislash nuit à la lisibilité du code, on peut délimiter la chaîne à l'aide de triples guillemets ou de triples apostrophes :

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

>>> print(a1)

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

Commentaires[modifier | modifier le wikicode]

Tout ce qui suit un dièse (#) jusqu'à un retour à la ligne est un commentaire : ce n'est pas pris en compte par l'interpréteur. Mais cette règle ne s'applique pas lorsque le dièse est positionné dans une chaîne de caractères (entre quotes).

Le but reste de produire du code compréhensible sans commentaire, mais ce texte affiché uniquement dans le code source, peut servir à expliquer à celui qui relit le code (y compris soi-même), les subtilités les moins évidentes de celui-ci.

# Toute cette première ligne est un commentaire.
print("Bonjour le monde") # Ceci est également un commentaire
print("Bonjour"); print("Le monde"); # Ceci est une ligne comportant
# plusieurs instructions
print("Cette ligne ne contient pas de #commentaire")
Exemple 1 : On notera que la fonction print affiche son argument.

Commentaires de bloc[modifier | modifier le wikicode]

Les commentaires de bloc (block comments en anglais) permettent de commenter plusieurs lignes. En Python, ils sont assurés par des triples apostrophes ou guillemets :

print('début')
'''
Le paragraphe suivant est commenté
sur plusieurs lignes
'''
print('fin')

Couleurs[modifier | modifier le wikicode]

Il est possible d'écrire en couleurs dans le terminal en précisant leurs codes[2]. Exemple :

print('\x1b[6;31;40m' + ' Texte rouge ' + '\x1b[0m')
print('\x1b[6;30;42m' + ' Fond vert ' + '\x1b[0m')

Références[modifier | modifier le wikicode]


Structure d'un programme

Les instructions[modifier | modifier le wikicode]

Un programme Python est composé d'instructions. Une instruction est un ordre unitaire donné à un programme. Par exemple afficher Bonjour est une instruction, de même que calculer un plus un.

La structure d'un programme Python est certainement ce qui étonne le plus le programmeur ayant l'habitude d'un langage plus traditionnel comme le C : en Python les limites des instructions et des blocs sont définies par la mise en page.

  • Le point-virgule (;) à la fin de chaque instruction est remplacé par le caractère de fin de ligne (symbolisé par "\n"). Ce qui simplifie la syntaxe car traditionnellement les points-virgules étaient toujours suivis de retours à la ligne.
  • Les accolades ({}) fréquemment utilisées pour définir les blocs sont remplacées par les niveaux d'indentations. En effet, il était déjà conseillé aux programmeurs de se servir aussi des sauts à la ligne et de l'indentation pour bien délimiter visuellement les blocs, donc c'est également un allègement du code.

En définitive, Python oblige à écrire du code lisible, et à prendre de bonnes habitudes conservables dans d'autres langages, ce qui est fait un langage idéal pour apprendre la programmation.

Les espaces sont ignorés[modifier | modifier le wikicode]

A part ceux qui servent à l'indentation, en début de ligne, les espaces placés à l'intérieur des instructions sont ignorés, sauf s'ils font partie d'une chaîne de caractères.

L'interpréteur Python commence par analyser la première ligne :

  • si celle-ci contient une instruction, alors il l'exécute
  • si l'instruction n'est pas une instruction de contrôle, alors, il passe à la ligne suivante, l'analyse et l'exécute
  • si le programme Python arrive à la fin du fichier à exécuter, alors, il sort du programme et en arrête l'exécution.
print "Bonjour"
1+1
c = 3e5
e = m*c**2
a, b, c = 1, 2, 3
discriminant = b**2-4*a*c
lambda x,y : x + y
dico1 = {'prénom':'Eric', 'nom':'tartempion'}
print ("Bonjour %s" % dico1['nom'])
Exemple 1 : quelques instructions


Notion de bloc d'instructions[modifier | modifier le wikicode]

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).

Un bloc d'instructions est une suite d'instructions qui est alignée sur la même tabulation. Les blocs d'instructions sont crées par les instructions de contrôles comme if, while et for, ainsi que par les instructions permettant de déclarer des fonctions.

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.

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

Il y a deux solutions pour indenter : utiliser quatre espaces ou un seul caractère tabulation, mais jamais un mélange des deux sous peine d'erreurs IndentationError: unindent does not match any outer indentation level. 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.

La tabulation est notamment la convention utilisée pour la librairie standard de Python, mais les espaces ont l'avantage de fonctionner avec tous les éditeurs (et ainsi, de pouvoir être plusieurs sur le même projet avec des éditeurs différents). On préférera donc 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", qui modifie ce que produit la touche tab.

S'il y a plusieurs instructions indentées sous la ligne d'en-tête, elles doivent l'être exactement au même niveau. 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.

#Ce bloc d'instruction est collé contre le bord gauche du fichier
print "Je suis dans le premier bloc"
print "Je suis toujours dans le premier bloc"

if (a == 12) : #L'instruction ''if'' initie un nouveau bloc
    #Ce bloc est a quatre espace du bord
    print "Je suis dans le second bloc"
    print "Je suis encore dans le second bloc"

    if (b == 13 ) :
        #Il est possible d'imbriquer des blocs dans des blocs
        print "Je suis dans un troisième bloc"
        print "et ici aussi"

    print "Je reviens dans le second bloc"

print "Je suis revenue dans le premier bloc"
Exemple 2 : Les blocs


Variables

Affectations[modifier | modifier le wikicode]

Début d’un principe
Fin du principe


En Python comme dans de nombreux autres langages, le symbole = est l'opérateur d'affectation. Cette valeur restera accessible jusqu'à la fin de l'exécution du programme (vérifiable avec "print(x)").

La valeur de la variable peut être un littéral, c'est-à-dire une constante, ou bien une expression (ex : une autre variable ou une instruction comme "1+1"). L'expression est évaluée avant d'être affectée à la variable.


Réaffectation[modifier | modifier le wikicode]

Si la variable affectée n'existe pas, l'ordinateur la crée, sinon il écrase sa valeur. En effet, il est permis de ré-affecter une nouvelle valeur à une même variable, autant de fois qu'on le souhaite.

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

Ceci nous amène à attirer 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

Affectations multiples[modifier | modifier le wikicode]

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

>>> x = y = 7
>>> x
7
>>> y
7

Affectations parallèles[modifier | modifier le wikicode]

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
 les francophones ont 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, etc.) comme on le voit dans notre exemple, pour les variables elles-mêmes ainsi que pour les valeurs qu'on leur attribue.

Exercices


  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.0
    
  2. Assignez les valeurs respectives 3, 5, 7 à trois variables a, b, c. Effectuez l'opération a - b/c . Le résultat est-il mathématiquement correct ? Si ce n'est pas le cas, comment devez-vous procéder pour qu'il le soit ?

Solution

Réfléchissez !

Principe de fonctionnement[modifier | modifier le wikicode]

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), 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, 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.

A cet emplacement est stocké 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 typographique, un tableau, une fonction, etc.

Exemple[modifier | modifier le wikicode]

Prenons l'exemple suivant :

>>> n = 7                       # donner à "n" la valeur "7"
>>> message = "Quoi de neuf ?"  # affecter la valeur "Quoi de neuf ?" à "message"
>>> 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", "message" 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é ;
  • 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 message 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.

Les références[modifier | modifier le wikicode]

Formellement, les variables Python sont des références, c'est à dire que écrire "a = ((1,0,0),(0,1,0),(0,0,1))" ne signifie pas que "a" vaut "((1,0,0),(0,1,0),(0,0,1))" mais que "a" référence le n-uplet "((1,0,0),(0,1,0),(0,0,1))". La différence est que ensuite, une autre variable peut référencer le même n-uplet, simplement avec "b = a". Si on modifie "b", alors "a" sera également modifié.

L'utilisation des références

>>> a = [(1,0,0), (0,1,0), (0,0,1)]
>>> b = a
>>> print (a)
[(1,0,0), (0,1,0), (0,0,1)]
>>> print (b)
[(1,0,0), (0,1,0), (0,0,1)]
>>> b[0] = (1,1,0)
>>> print (b)
[(1,1,0), (0,1,0), (0,0,1)]
>>> print (a)
[(1,1,0), (0,1,0), (0,0,1)]

Notez que a et b ne sont pas "liés", ils référencent simplement le même objet.

Si ensuite on fait référence à un nouvel objet (par l'intermédiaire de l'opérateur d'affectation "="), b référencera toujours l'ancien objet, et une modification de l'un des objets ne modifiera pas l'autre.

Indépendances des variables

>>> a = [1,2,3]
>>> b = a
>>> print (a)
[1,2,3]
>>> print (b)
[1,2,3]
>>> a = [4,5,6]
>>> print (b)
[1,2,3]
>>> print (a)
[4,5,6]
>>> a.append(7)
>>> print (a)
[4,5,6,7]
>>> print (b)
[1,2,3]

Idem pour les nombres :

Références et nombres

>>> a = 5
>>> b = a
>>> print (a)
5
>>> print (b)
5
>>> b += 5
>>> print (b)
10
>>> print (a)
5


Noms des variables[modifier | modifier le wikicode]

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 "longitude" et "latitude" conviennent mieux que "x" et "y", car 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.
  • La casse est significative (les caractères majuscules et minuscules sont distingués). Donc "Joseph", "joseph", et "JOSEPH" sont des variables différentes.
  • les 29 « mots réservés » du langage sont déjà pris (ex : "print").
  • Seules les lettres du code ASCII 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é).
 sous Python 3 les règles de nommage ont étés assouplies, car il devient possible d'utiliser n'importe quel caractère Unicode non opérateur dans les noms.

Il faut également noter que les variables dont le nom commence par le caractère _ ont une signification particulière :

  • les noms commençant par un _ ne sont pas exportés lorsqu'ils se trouvent dans un module ;
  • les noms commençant par deux _ et finissant par deux _ sont réservés par le langage lui même, notamment pour la programmation orientée objet.
Les noms suivants ne peuvent pas être utilisés comme nom de variable

 41toto  # On ne commence pas par un chiffre
 élément # Contient un caractère accentué, qui ne sont pas autorisés

De plus, il est recommandé d'écrire les noms de variables avec une minuscule, car l'usage veut qu'on le réserve plutôt la majuscule aux noms de classes.

Si le nom d'une variable doit comporter plusieurs mots, il y a deux possibilités d'écrire le nom de la variable :

  • En snake_case (à la C), c'est à dire en séparant les mots par le caractère "_". Exemple : marge_brut.
  • En CamelCase (à la Java), c'est à dire en séparant les mots par un passage en haut de casse (lettre majuscule). Exemple : margeBrut.

Il convient aussi d'éviter autant que possible l'énumération de variables (toto1, toto2, toto3, ...), cela rend le programme parfaitement incompréhensible et sujet à des erreurs.

Il est possible de préfixer le nom de la variable par son type. Par exemple int_margeBrut, str_message_de_bienvenue, mais cela alourdit très fortement le programme. On pourra par exemple s'inspirer de la notation hongroise qui formalise ce mécanisme.

Sinon, d'autres notations existent ou peuvent être imposées en fonction d'un projet, des habitudes d'une entreprise, etc.


Références[modifier | modifier le wikicode]


Opérateurs

Définition[modifier | modifier le wikicode]

Un opérateur est un symbole (ou un mot réservé) utilisé pour effectuer une opération entre des opérandes.

Une opérande est une variable, un littéral ou bien une expression.

Une expression est une suite valide d'opérateurs et d'opérandes.

Par exemple, dans l'expression :

x = y + 1

Il y a deux opérateurs ( = et +) et trois opérandes (x, y et 1).

Certains opérateurs peuvent avoir des comportements différents en fonction des types d'opérandes sur lesquels ils agissent : on parle alors de surcharge des opérateurs. Exemple :

  • "+" additionne des nombres, mais concatène des chaines de caractères.
  • "*" multiplie des nombres entre eux, mais duplique des chaines de caractères.

Il existe différentes catégories d'opérateur :

Présentation des différents opérateurs[modifier | modifier le wikicode]

les opérateurs d'affectation[modifier | modifier le wikicode]

  • '='
  • Affectation multiple, e.g. x = y = z = 3
  • Affectation parallèle, e.g. x, y = 1 , 0.5

les opérateurs logiques[modifier | modifier le wikicode]

Les expressions avec un opérateur logique sont évaluées à "True" ou "False".

  • X or Y : OU logique.
    Si X est évalué à True, alors l'expression est True et Y n'est pas évalué.
    Sinon, l'expression est évaluée à la valeur booléenne de Y.
  • X and Y : ET logique.
    Si X est évalué à False, alors l'expression est False et Y n'est pas évalué.
    Sinon, l'expression est évaluée à la valeur booléenne de Y.
  • not X : NON logique.
    Evalué à la valeur booléenne opposée de X.

les opérateurs de comparaisons[modifier | modifier le wikicode]

Tout comme les opérateurs logiques, les opérateurs de comparaison renvoient une valeur booléenne "True" ou "False". Les opérateurs de comparaisons s'appliquent sur tous les types de base.

  • < strictement inférieur
  • > strictement supérieur
  • <= inférieur ou égal
  • >= supérieur ou égal
  • == égal
  • != différent
  • <> différent, on utilisera de préférence !=
  • X is Y : X et Y représentent le même objet.
  • X is not Y : X et Y ne représentent pas le même objet

Il est possible d'enchaîner les opérateurs : X < Y < Z, dans ce cas, c'est Y qui est pris en compte pour la comparaison avec Z et non pas l'évaluation de (X < Y) comme on pourrait s'y attendre dans d'autres langages.

les opérateurs mathématiques[modifier | modifier le wikicode]

symbole types exemples
+ entier, réel

chaîne de caractères

6+4 == 10

"s" + "s"== "ss"

- entier, réel 6-4 == 2
* entier

réel

chaîne de caractères

6*4 == 24

1.2 * 1 == 1.2

3 * "s" == "sss"

** entier, réel 12**2 == 144
/ entier

réel

6/4 == 1 (*)

6./4 == 1.5

// entier, réel 6//4 == 1
% entier, réel 6%4 == 2

(*) Attention à la division en Python 2.7 et Python 3.5

Priorité des opérations[modifier | modifier le wikicode]

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-2*2 renvoie -2 et non 0 !Et 2+4/2 renvoie 4.0 et non 3.0 (Rappelez-vous que / est l'opérateur de la division décimale).
    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.0. Si la division était effectuée en premier, le résultat serait 59.0 (rappelez-vous ici encore qu'il s'agit d'une division classique).
  • A et S pour addition et soustraction.
Précédence des opérateurs (du plus au moins prioritaire[1])
Symbole Nom
{} Dictionnaire
() Argument
[] Partie (opérateur d'indiçage)
. Attribut
** Puissance
~ inversion de bit
+ Positif
- Négatif
* Multiplier
/ Diviser
// Résultat entier d'une division
% Modulo
Plus
Moins
<< Décalage à gauche
>> Décalage à droite
& et logique
^ ou exclusif
| ou logique
< inférieur
> supérieur
<= inférieur ou égal
>= supérieur ou égal
== est égal
!= est différent
is est
in appartient
not non booléen
and et booléen
or ou booléen
lambda expression lambda

Références[modifier | modifier le wikicode]


Opérateurs et expressions[modifier | modifier le wikicode]

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". 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. A cette valeur, il attribue automatiquement un type, lequel dépend de ce qu'il y a dans l'expression. Dans l'exemple ci-dessus, la variable "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. Il faut leur 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, etc.

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

>>> 10 % 3  # 1
>>> 10 % 5  # 0

Cet opérateur pourra être utile 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.

Exercices

  1. Testez les lignes d'instructions suivantes :
    >>>  r , pi = 12, 3.14159
    >>>  s = pi * r**2
    >>>  print(s)
    452.38896
    >>>print(type(r), type(pi), type(s))
    <type 'int'>, <type 'float'>, <type 'float'>
    

    Solution On constate qu'une variable appartenant à l'ensemble des nombres entiers, multipliée par un nombre décimal, donne un décimal.

Composition[modifier | modifier le wikicode]

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 :

Il y a une limite à ce que vous pouvez combiner ainsi. Le symbole pour l'égalité en mathématique est '='. Le symbole pour l'égalité en programmation Python est '=='

Ainsi par exemple,

  • En mathématique : a + 1 = b ( '=' est symbole de l'égalité et ici on a une équation). m + 1 = b et a * x = b sont ici des équations mathématiques. Cette forme d’écriture est inutilisable pour modifier une variable en programmation.
  • En programmation (Python et dans d'autres langages) : on peut écrire a = a + 1 ( '=' est l'opérateur d'affectation, symbole d'affectation). On affecte à la variable a, à gauche, un nouveau contenu. Cela signifie ici (en programmation uniquement) que la nouvelle valeur de a ( à gauche du signe d'affectation) va être remplacée par l'ancienne valeur de a ( à droite du signe d'affectation) incrémentée ici de la valeur 1. Avec a = a - 2 on décrémente la variable a de la valeur 2.

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


Structures de contrôle

Définition[modifier | modifier le wikicode]

Début d’un principe
Fin du principe


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 :

  1. la séquence (ex : chaînes de caractères, tuples et listes) ;
  2. la sélection ;
  3. la répétition.

Séquence d'instructions[modifier | modifier le wikicode]

 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.

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

Python exécute normalement les instructions de la première à la dernière, sauf lorsqu'il rencontre une instruction conditionnelle comme l'instruction "if". Une telle instruction va permettre au programme de suivre différents chemins suivant les circonstances.

Sélection ou exécution conditionnelle[modifier | modifier le wikicode]

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", qui permet de tester une condition et de n'exécuter les instructions que si cette condition est vérifiée. Exemple :

a = 11
if a > 10 :
    print("a est plus grand que dix")

En exécutant ce programme, on voit "a est plus grand que dix" apparaître à l'écran. On peut perfectionner le programme pour prendre en compte le cas ou "a" est plus petit que dix :

if a > 10 :
    print("a est plus grand que dix")
else:
    print("a n'est pas plus grand que dix")

On utilise aussi parfois "elif" (contraction de "else if") :

if a > 10 :
    print("a est plus grand que dix")
elif a == 10:
    print("a est égal à dix")
else:
    print("a est plus petit que dix")


 en exécutant un "if" dans l'IDLE, on constate que le prompt principal (>>>) est maintenant remplacé par un prompt secondaire constitué de trois points (du moins sur Linux).
>>> if (a > 10):
...     

L'expression entre parenthèses est ce que nous appellerons désormais une condition. L'instruction "if" permet de tester la validité de cette condition, une expression contenant un opérateur de comparaison. 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.

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. Mais on peut enchainer autant de conditions que nécessaires en utilisant avant l'instruction "elif" (contraction de « else if »).

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")
...

Dans cet exemple, 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[modifier | modifier le wikicode]

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 :

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

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 6) 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 & 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.

pass[modifier | modifier le wikicode]

De manière générale, un bloc contient tout le code avec une même indentation.

ceci est le bloc principal
if condition:
    bloc 2
    if condition2:
        bloc 3
    fin du bloc 2
fin du bloc 1

Si à un endroit on a syntaxiquement besoin d'un bloc mais qu'il n'y a rien à faire, on peut utiliser l'instruction pass, qui justement ne fait rien.

if condition:
    pass
else:
    instruction



Instructions répétitives

L'instruction "while"[modifier | modifier le wikicode]

Cette instruction est une boucle, c'est-à-dire qu'elle permet de répéter plusieurs fois un bloc d'instructions (en boucle).

"while" exécute des commandes tant qu'une ou plusieurs conditions sont vraies.

while condition:
   commandes

par exemple :

i = 0
while i < 5:
   i = i + 1
   print(i)

donne à l'exécution :

1 2 3 4 5

En effet, 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 à "5".

Comme l'instruction "if", 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.

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èses (celles-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.
  • 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'instruction "print" qui affiche 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 < 5 est encore vraie, le corps de la boucle est exécuté une nouvelle fois et le bouclage se poursuit.

Remarques[modifier | modifier le wikicode]

  • 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), en risquant de saturer les processeurs (si cela survient, presser CTRL + C pour annuler le lancement). 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 condition puisse devenir fausse et donc que la boucle se termine.

Exemple de boucle infinie (à éviter) :

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

Exemple : élaboration d'une table de multiplication.

>>> a = 0
>>> while a < 12:
...     a = a + 1
...     print(a, a**2 , a**3)
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
11 121 1331
12 144 1728

On obtient donc la liste des carrés et des cubes des nombres de 1 à 12.

Construction d'une suite mathématique[modifier | modifier le wikicode]

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,                 # print ( b , end=" " ) avec python3
...    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 à la virgule placée à la fin de la ligne qui contient l'instruction "print". Si vous supprimez cette virgule, les nombres seront affichés l'un en-dessous de l'autre.

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 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

  1. Écrivez un programme qui affiche les 20 premiers termes de la table de multiplication par 7.
  2. É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)
    
  3. Écrivez un programme qui affiche une suite de 12 nombres dont chaque terme soit égal au triple du terme précédent.

Solution

  1. >>> c = 0
    >>> while c < 20:
    ...     c = c +1
    ...     print c, "x 7 =", c*7
    

    ou encore :

    >>> c = 1
    >>> while c <= 20:
    ...     print c, "x 7 =", c*7
    ...     c = c +1
    
  2. >>> s = 1
    >>> while s <= 16384:
    ...     print s, "euro(s) =", s *1.65, "dollar(s)"
    ...     s = s *2
    
  3. >>> a, c = 1, 1
    >>> while c < 13:
    ...     print a,
    ...     a, c = a *3, c+1
    


Exercices

  1. Ecrivez 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.
  2. Ecrivez un programme qui convertisse 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 : %).
  3. Ecrivez 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. Ecrivez 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.
  5. Ecrivez un programme qui affiche la suite de symboles suivante :
    *
    **
    ***
    ****
    *****
    ******
    *******
    

Solution

  1. Réfléchissez !
  2. # Le nombre de secondes est fourni au départ :
    # (un grand nombre s'impose !)
    nsd = 12345678912
    # Nombre de secondes dans une journée :
    nspj = 3600 * 24
    # Nombre de secondes dans un an (soit 365 jours -
    # on ne tiendra pas compte des années bissextiles) :
    nspa = nspj * 365
    # Nombre de secondes dans un mois (en admettant
    # pour chaque mois une durée identique de 30 jours) :
    nspm = nspj * 30
    # Nombre d'années contenues dans la durée fournie :
    na = nsd / nspa         # division <entière> 
    nsr = nsd % nspa        # n. de sec. restantes
    # Nombre de mois restants :
    nmo = nsr / nspm        # division <entière> 
    nsr = nsr % nspm        # n. de sec. restantes
    # Nombre de jours restants :
    nj = nsr / nspj         # division <entière> 
    nsr = nsr % nspj        # n. de sec. restantes
    # Nombre d'heures restantes :
    nh = nsr / 3600         # division <entière> 
    nsr = nsr % 3600        # n. de sec. restantes
    # Nombre de minutes restantes :
    nmi = nsr /60           # division <entière> 
    nsr = nsr % 60          # n. de sec. restantes
    
    print "Nombre de secondes à convertir :", nsd
    print "Cette durée correspond à", na, "années de 365 jours, plus"
    print nmo, "mois de 30 jours,",
    print nj, "jours,",
    print nh, "heures,",
    print nmi, "minutes et",
    print nsr, "secondes."
    
  3. 
    # affichage des 20 premiers termes de la table par 7,
    # avec signalement des multiples de 3 :
    
    i = 1               # compteur : prendra successivement les valeurs de 1 à 20
    while i < 21:
        # calcul du terme à afficher :
        t = i * 7
        # affichage sans saut à la ligne (utilisation de la virgule) :
        print t,
        # ce terme est-il un multiple de 3 ? (utilisation de l'opérateur modulo) :
        if t % 3 == 0:
            print "*",      # affichage d'une astérisque dans ce cas
        i = i + 1           # incrémentation du compteur dans tous les cas
    
  4. Réfléchissez !
  5. Réfléchissez !

L'instruction "for"[modifier | modifier le wikicode]

La boucle "for" permet d'exécuter une itération un certain nombre de fois :

>>> for i in range(5):
...    print(i)
1
2
3
4
5

Pour le "foreach" (répétition pour chaque élément d'un itérable) :

>>> for champ in ['champ1', 'champ2', 'champ3']: 
...    print(champ)
champ1
champ2
champ3

Les instructions "break", "continue"[modifier | modifier le wikicode]

L'instruction "break" permet d'arrêter une boucle avant sa fin. L'instruction "continue" est similaire, mais au lieu d'interrompre la boucle, elle permet de passer à l'itération suivante.

for i in range(5):
    if i==3:
        break
    print i

affichera

0 1 2

tandis que

for i in range(5):
   if i==3:
        continue
   print i

affichera

0 1 2 4


Types

Typage des variables[modifier | modifier le wikicode]

Début d’un principe
Fin du principe


Python est un langage à typage dynamique. Cela signifie que bien que gérant différents types, lorsqu'une variable est affectée, l'interpréteur trouvera automatiquement son type sans que l'utilisateur soit contraint de le préciser. 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.

Par opposition, le typage statique est préférable dans le cas des langages compilés comme 'C++ et Java, parce qu'il permet d'optimiser l'opération de compilation (dont le résultat est un code binaire « figé »). 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 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.


Types natifs[modifier | modifier le wikicode]

Liste des types
int Nombre entier optimisé
long Nombre entier de taille arbitraire
float Nombre à virgule flottante
complex Nombre complexe
str Chaîne de caractère
unicode Chaîne de caractère unicode
tuple Liste de longueur fixe
list Liste de longueur variable
dict dictionnaire
file Fichier
bool Booléen
NoneType Absence de type
NotImplementedType Absence d'implementation
function fonction
module module


Tableau 2 : Liste des types prédéfinis en Python
Tableau des types Python 3.x ayant changé de nom depuis 2.x
nom description équivalent 2.x
int nombre entier de longueur arbitraire long
byte chaîne de caractères ASCII str
str chaîne de caractères Unicode unicode

Détermination d'un type[modifier | modifier le wikicode]

La fonction type() permet de connaître le type d'une variable.

>>> a=3
>>> type(a)
<type 'int'>
Exemple 1 : utilisation de la fonction type

Conversion des types[modifier | modifier le wikicode]

Il existe plusieurs fonctions qui permettent de forcer le type d'une variable en un autre type.

  • int() : permet de modifier une variable en entier. Provoque une erreur si cela n'est pas possible.
  • long() : transforme une valeur en long.
  • str() : permet de transformer la plupart des variables d'un autre type en chaînes de caractère.
  • float() : permet la transformation en flottant.
  • repr() : similaire à "str". Voir la partie sur les objets
  • eval() : évalue le contenu de son argument comme si c'était du code Python.
  • split() : sépare une chaine en liste.
  • join() : transforme une liste en chaine, dont le séparateur est en préfixe (" ".join(MaListe)).
  • datetime.strptime('20170727222900', '%Y%m%d%H%M%S') : change une chaine en date.
  • maDate.strftime('%Y%m%d%H%M%S') : change une date en chaine.


Numériques

Il existe deux types pour définir des nombres entiers : le type int et le type long. Il existe également un type pour représenter des nombres à virgule : le type float.

Les nombres entiers de type int[modifier | modifier le wikicode]

Les int représentent le type le plus facilement représentable sur une architecture donnée. Par exemple, sur une machine 32-bits, la taille d'un int sera de 32-bit, donc un int permettra de représenter des nombres entre et , soit entre -2 147 483 648 et 2 147 483 647.

Un littéral int s'écrit tout simplement avec les chiffres de 0 à 9, précédé éventuellement du symbole -. Il est possible d'écrire ce littéral suivant trois bases :

  • la base décimale : le littéral devra commencer par un chiffre entre 1 et 9
  • la base octale (base 8) : le littéral devra commencer par 0 suivi de chiffres de 0 à 7
  • la base hexadécimale (base 16): le littéral devra commencer par 0x suivi de chiffres de 0 à 9 et de lettres de A à F (en minuscule ou majuscule)
x=1
x=0
x=-33
x=4566
x=2147483647
x=076 #équivalent à x=62
x=0xFF #équivalent à x=255
x=0xa1 #équivalent à x=161
Exemple 2 : Quelques entiers int'

Les nombres entiers de type long[modifier | modifier le wikicode]

Un entier long est un entier dont la taille n'est limitée que par la mémoire allouée par l'ordinateur à l'interpréteur Python. C'est à dire qu'un long permet d'écrire des entiers aussi grands que l'on veut.

Il existe deux manières d'utiliser des long :

  • il faut rajouter L ou l à la fin d'un littéral entier pour qu'il soit automatiquement long
  • lorsque le résultat d'une opération dépasse la capacité de stockage d'un int, alors, ce résultat est automatiquement convertit en long
x=1L
x=-45l
x=121212121212121212121212121 #Automatiquement converti en long
x=2147483647+1
Exemple 3 : Quelques entiers long'

Il n'est pas nécessaire d'utiliser le type long de manière systématique : pour les entiers de taille raisonnable, le type int est beaucoup plus optimisé.

Pour convertir un long en int (et inversement), il est possible d'utiliser les fonctions int() et long().

x = int(1L) #x est un int
x = long(1) #x est un long
x = int(12121212121212121) #x est quand même un long
Exemple 4 : Utilisation des fonctions int() et long()

Limite entre « integer » et « long »[modifier | modifier le wikicode]

Début d’un principe
Fin du principe


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. À priori, il suffit de modifier la condition de bouclage, dans la deuxième ligne. Avec while c<49:, nous devrions obtenir quarante-huit 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<49:
        print c, " : ", b, type(b)
        a, b, c = b, a+b, c+1
...
...
...  (affichage des 43 premiers termes)
... 
44  :  1134903170 <type 'int'>
45  :  1836311903 <type 'int'>
46  :  2971215073 <type 'long'>
47  :  4807526976 <type 'long'>
48  :  7778742049 <type 'long'>

Que pouvons-nous constater ?

Si nous n'avions pas utilisé la fonction type(), qui nous permet de vérifier à chaque itération le type de la variable b, nous n'aurions rien remarqué du tout : la suite des nombres de Fibonacci s'affiche sans problème (et nous pourrions encore l'allonger de nombreux termes supplémentaires).

Il semble donc que Python soit capable de traiter des nombres entiers de taille illimitée.

L'exercice que nous venons de réaliser indique cependant qu'il se passe « quelque chose » lorsque ces nombres deviennent très grands. Au début du programme, les variables a, b et c sont définies implicitement comme étant du type integer. C'est ce qui se passe toujours avec Python lorsqu'on affecte une valeur entière à une variable, à condition que cette valeur ne soit pas trop grande. Dans la mémoire de l'ordinateur, ce type de donnée est en effet encodé sous la forme d'un bloc de 4 octets (ou 32 bits). Or la gamme de valeurs décimales qu'il est possible d'encoder sur 4 octets seulement s'étend de -2147483648 à + 2147483647 (Voir cours d'informatique générale).

Les calculs effectués avec ce type de variable sont toujours très rapides, parce que le processeur de l'ordinateur est capable de traiter directement par lui-même de tels nombres entiers à 32 bits. 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 savez déjà que le type des variables Python est défini de manière dynamique.

Puisqu'il s'agit du type le plus performant (aussi bien en termes de vitesse de calcul qu'en termes d'occupation de place dans la mémoire), Python utilise le type integer par défaut, chaque fois que cela est possible, c'est-à-dire tant que les valeurs traitées sont des entiers compris entre les limites déjà mentionnées plus haut (environ 2 milliards, en positif ou en négatif).

Lorsque les valeurs traitées sont des nombres entiers se situant au-delà de ces limites, leur encodage dans la mémoire de l'ordinateur devient plus complexe. Les variables auxquelles on affecte de tels nombres sont alors automatiquement définies comme appartenant au type « entier long » (lequel est désigné par long dans la terminologie Python).

Ce type long permet l'encodage de valeurs entières avec une précision quasi infinie : une valeur définie sous cette forme peut en effet posséder un nombre de chiffres significatifs quelconque, ce nombre n'étant limité que par la taille de la mémoire disponible sur l'ordinateur utilisé !

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
>>> 

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.

Au départ, les variables a, b et c sont du type integer, puisqu'on leur affecte des petites valeurs numériques entières : 3, 2 et 1. A partir de la 8e itération, cependant, les variables b et a sont automatiquement converties l'une après l'autre dans le type long : le résultat de la multiplication des termes 6 et 7 est en effet déjà bien supérieur à la limite des 2 milliards évoquée plus haut.

La progression continue avec des nombres de plus en plus gigantesques, mais la vitesse de calcul diminue. Les nombres mémorisés sous le type long occupent une place variable dans la mémoire de l'ordinateur, en fonction de leur taille.

Les nombres à virgule flottante (float)[modifier | modifier le wikicode]

Un nombre à virgule flottante est un nombre décimal qu'il est possible de représenter par sa mantisse et son exposant. Par exemple, le nombre 125,789 est représentable par le couple (mantisse = 1,25789, exposant = 2). La mantisse étant toujours comprise entre -10 et 10 exclus.

Les nombres sont traduits par la formule .

Les limites dépendent de l'architecture de la machine et sont équivalentes au type de donnée double du langage C.

Les littéraux peuvent s'écrire avec les chiffres, le caractère point pour indiquer la séparation entre la partie entière et la partie décimale et la lettre 'e' ou 'E' pour spécifier l'exposant.

x = 1.234
x = 1.0 #Notons qu'un entier peut être un flottant
x = 1. #Même résultat que précédemment
x = 1.234e54 #C'est à dire <math>1.234*10^{54}</math>
x = 1.234E54 #idem
x = -1.454e-2 #La mantisse et l'exposant peuvent être négatifs
Exemple 5 : nombres à virgules

Essayons donc ce type de données dans un nouveau petit programme :

>>> 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 10e-308 et 10e+308 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

  1. Écrivez un programme qui convertisse en radians un angle fourni au départ en degrés, minutes, secondes.
  2. Écrivez un programme qui convertisse en degrés, minutes, secondes un angle fourni au départ en radians.
  3. Écrivez un programme qui convertisse en degrés Celsius une température exprimée au départ en degrés Fahrenheit, ou l'inverse.
    La formule de conversion est :
  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 taux fixe de 4,3 %
  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 64e 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)

Solution

  1. # Conversion degrés -> radians
    # Rappel : un angle de 1 radian est un angle qui correspond à une portion
    # de circonférence de longueur égale à celle du rayon.
    # Puisque la circonférence vaut 2 pi R, un angle de 1 radian correspond
    # à 360° / 2 pi , ou encore à 180° / pi
    
    # Angle fourni au départ en degrés, minutes, secondes :
    deg, min, sec  = 32, 13, 49
    
    # Conversion des secondes en une fraction de minute :
    # (le point décimal force la conversion du résultat en un nombre réel)
    fm = sec/60.
    # Conversion des minutes en une fraction de degré :
    fd = (min + fm)/60
    # Valeur de l'angle en degrés "décimalisés" :
    ang = deg + fd
    # Valeur de pi :
    pi = 3.14159265359
    # Valeur d'un radian en degrés :
    rad = 180 / pi
    # Conversion de l'angle en radians :
    arad = ang / rad
    # Affichage :
    print deg, "°", min, "'", sec, '" =', arad, "radian(s)"
    
  2. Réfléchissez !
  3. # Conversion °Fahrenheit <-> °Celsius
    
    # A) Température fournie en °C :
    tempC = 25
    # Conversion en °Fahrenheit :
    tempF = tempC * 1.8 + 32
    # Affichage :
    print tempC, "°C =", tempF, "°F"
    
    # B) Température fournie en °F :
    tempF = 25
    # Conversion en °Celsius :
    tempC = (tempF - 32) / 1.8
    # Affichage :
    print tempF, "°F =", tempC, "°C"
    
  4. Réfléchissez !
  5. >>> a, b = 1, 1				# variante :  a, b = 1., 1
    >>> while b<65:
    ...     print b, a
    ...     a,b = a*2, b+1
    ...
    

Les nombres complexes[modifier | modifier le wikicode]

Python est un des rares langages à proposer un type de base pour les nombres complexes . Un nombre complexe est un nombre composé d'une partie réelle et d'une partie imaginaire. On note une des racines du polynôme .

Dans certains contextes, (comme la physique), la racine de -1 est notée j. C'est ce qui se fait en Python.

Un littéral complexe s'écrit donc : a + bj, avec a et b des variables de type float. Attention, j doit être précédé d'un nombre car sinon, Python l'interprétera comme étant la variable j. Il ne doit pas y avoir d'espace entre ce nombre et j.

x = 1 + 1j
x = 1.2e3 + 1.5e7j
x = 5j + 4 
x = 1 + x*1j
Exemple 5 : quelques nombres complexes


Booléens

Définition[modifier | modifier le wikicode]

Un booléen est un type de données qui ne peut prendre que deux valeurs : vrai ou faux. En Python, les constantes littérales sont notées True et False.

Tous les types de variables peuvent être interprétés de manière booléenne. Par exemple, pour les entiers (int), la valeur "0" correspond à "faux" et les autres valeurs à "vrai". Il en est de même pour tous les autres types : une valeur particulière vaut False et le reste des valeurs True. Le tableau suivant présente les valeurs "faux" pour les principaux type de données.

Exemple d'expressions booléennes[modifier | modifier le wikicode]

a = 6
b = 7
c = 42
print(1, a == 6)
print(2, a == 7)
print(3, a == 6 and b == 7)
print(4, a == 7 and b == 7)
print(5, not a == 7 and b == 7)
print(6, a == 7 or b == 7)
print(7, a == 7 or b == 6)
print(8, not (a == 7 and b == 6))
print(9, not a == 7 and b == 6)

Affiche :

1 True
2 False
3 True
4 False
5 True
6 True
7 False
8 True
9 False

Que se passe-t-il ? Le programme consiste en un tas de print. Chaque print affiche un nombre et une expression. Le nombre sert à savoir de quel ligne on parle. Notez bien comme chaque expression finit soit par False ou True. En python False et True peuvent aussi être écrits 0 et 1.

And[modifier | modifier le wikicode]

Voyez ce code :

print(1, a == 6)
print(2, a == 7)

Cela affiche respectivement a True et a False comme attendu, le premier est vrai, et le second est faux. La troisième ligne, print(3, a == 6 and b == 7), est un peu différente. L'opérateur and signifie que si les deux expressions qui l'entourent sont vraies alors toute l'expression l'est également, autrement elle est fausse. Le comportement de and peut être résumé comme suit :

Expression Résultat
True and True True
True and False False
False and True False
False and False False

Notez que si la première expression est fausse Python ne vérifie pas la seconde car il sait que l'expression car il sait que tout l'expression est fausse. Essayez de lancer False and print("Salut") et comparez le à True and print("Salut"). Le terme technique pour ceci est short-circuit evaluation (littéralement "évaluation en circuit court").

Not[modifier | modifier le wikicode]

La ligne suivante, print(5, not a == 7 and b == 7), utilise l'opérateur not. not retourne l'opposé d'un expression (l'expression pourrait être réécrite print(5, a != 7 and b == 7)). Voici la table de vérité :

Expression Résultat
not True False
not False True

Or[modifier | modifier le wikicode]

Les deux lignes suivantes, print(7, a == 7 or b == 7) et print(7, a == 7 or b == 6) utilisent l'opérateur or. or retourne vrai si la première expression est vraie ou si la seconde expression est vraie, si la seconde expression est vraie ou si les deux le sont. Si aucune n'est vraie il retourne faux. Voici sa table de vérité :

Expression Résultat
True or True True
True or False True
False or True True
False or False False

Notez que si la première expression est vraie Python ne vérifie pas la seconde expression car il sait que toute l'expression est vraie. Cela marche car or est vrai si au moins une des expressions est vraie. La première partie est vraie donc la seconde pourrait être vraie ou fausse, mais l'expression est toujours vraie.

Les deux lignes suivantes, print(8, not (a == 7 and b == 6)) et print(9, not a == 7 and b == 6, montrent que les parenthèses peuvent être utilisées pour regrouper des expressions et forcer l’évaluation d'une partie en premier. Notez que les parenthèses ont changé l'expression de "faux" à "vrai". La raison est que les parenthèses ont forcé le not à s'appliquer à toute l'expression au lieu de seulement la partie a == 7.

bool()[modifier | modifier le wikicode]

La valeur booléenne d'une variable "x" peut être obtenue avec bool(x). Voici la table de vérité selon le type de la variable :

Vrai Faux
True False
1 0
Nombre (positif ou négatif) None
Chaine non vide Chaine vide
Liste non vide Liste vide
Dictionnaire non vide Dictionnaire vide

Pour tester si une variable "x" n'est pas nulle, on utilise : not x is None.

Note sur les opérateurs booléens[modifier | modifier le wikicode]

Attention !
link={{{link}}}

x == ('a' or 'b') n'est pas équivalent à x == 'a' or x == 'b'. En effet, cela ne vérifie pas si x est équivalent aux caractères 'a' ou 'b', car l'expression booléenne s'arrête avant la fin par short-circuit evaluation.

Exemple :

 >>> 'a' == ('a' or 'b')  # 'a' = True, donc ('a' or 'b') = 'a' sans avoir à évaluer 'b'. Ce qui revient à : 'a' == 'a'
 True

 >>> 'b' == ('a' or 'b')  # Revient à : 'b' == 'a', de la même manière
 False 

 >>> 'a' == ('a' and 'b') # 'a' = True et 'b' = True, donc ('a' and 'b') = 'b' (dernière expression évaluée). Ce qui revient à : 'a' == 'b'
 False

 >>> 'b' == ('a' and 'b') # Revient à : 'b' == 'b', de la même manière
 True

Véracité/fausseté d'une expression[modifier | modifier le wikicode]

Lorsqu'un programme contient des instructions telles que while ou if, l'ordinateur qui exécute ce programme doit évaluer la véracité d'une condition, c'est-à-dire déterminer si une expression est vraie ou fausse. Par exemple, une boucle initiée par while c<20: s'exécutera aussi longtemps que la condition c<20 restera vraie.

Mais comment un ordinateur peut-il déterminer si quelque chose est vrai ou faux ?

En fait - et vous le savez déjà - un ordinateur ne manipule strictement que des nombres. Tout ce qu'un ordinateur doit traiter doit d'abord toujours être converti en valeur numérique. Cela s'applique aussi à la notion de vrai/faux. En Python, tout comme en C, en Basic et en de nombreux autres langages de programmation, on considère que toute valeur numérique autre que zéro est « vraie ». Seule la valeur zéro est « fausse ». Exemple :

a = input('Entrez une valeur quelconque')
if a:
    print "vrai"
else:
    print "faux"

Le petit script ci-dessus n'affiche « faux » que si vous entrez la valeur 0. Pour toute autre valeur numérique, vous obtiendrez « vrai ».

Si vous entrez une chaîne de caractères ou une liste, vous obtiendrez encore « vrai ». Seules les chaînes ou les listes vides seront considérées comme « fausses ».

Tout ce qui précède signifie donc qu'une expression à évaluer, telle par exemple la condition a > 5 , est d'abord convertie par l'ordinateur en une valeur numérique. (Généralement 1 si l'expression est vraie, et zéro si l'expression est fausse). Exemple :

a = input('entrez une valeur numérique : ')
b = (a < 5)
print 'la valeur de b est', b, ':'
if b:
    print "la condition b est vraie"
else:
    print "la condition b est fausse"

Le script ci-dessus vous renvoie une valeur b = 1 (condition vraie) si vous avez entré un nombre plus petit que 5.

Ces explications ne sont qu'une première information à propos d'un système de représentation des opérations logiques de l’algèbre de Boole.

Exemple[modifier | modifier le wikicode]

Créer le fichier password1.py :

#!/usr/bin/python
# -*- coding:Utf-8 -*-
# Ce programme demande à l'utilisateur son nom et son mot de passe, puis il les vérifie

name = input("What is your name? ")
password = input("What is the password? ")
if name == "Josh" and password == "Friday":
    print("Welcome Josh")
elif name == "Fred" and password == "Rock":
    print("Welcome Fred")
else:
    print("I don't know you.")

Résultats :

 What is your name? Josh
 What is the password? Friday
 Welcome Josh

 What is your name? Bill
 What is the password? Money
 I don't know you.

Exercices

Écrire un programme devine votre nom, avec seulement trois chances avant de terminer.


Solution

#!/usr/bin/python
# -*- coding:Utf-8 -*-

print("Try to guess my name!")
count = 1
name = "guilherme"
guess = input("What is my name? ")
while count < 3 and guess.lower() != name:    # .lower permet ici d'ignorer les majuscules dans le nom
    print("You are wrong!")
    guess = input("What is my name? ")
    count = count + 1

if guess.lower() != name:
    print("You are wrong!")
    print("You ran out of chances.")
else:
    print("Yes! My name is"), name + "!"


Chaines de caractères

Les données alphanumériques[modifier | modifier le wikicode]

Début d’un principe
Fin du principe


A la différence des données numériques, qui sont des entités singulières, les chaînes de caractères (ou string) constituent un type de donnée composite. Nous entendons par là une entité bien définie qui est faite elle-même d'un ensemble d'entités plus petites, en l'occurrence : les caractères. Suivant les circonstances, nous serons amenés à traiter une telle donnée composite, tantôt comme un seul objet, tantôt comme une suite ordonnée d'éléments. Dans ce dernier cas, nous souhaiterons probablement pouvoir accéder à chacun de ces éléments à titre individuel.

En fait, les chaînes de caractères font partie d'une catégorie d'objets Python que l'on appelle des séquences, et dont font partie aussi les listes et les tuples.

Le type « string »[modifier | modifier le wikicode]

Sous Python, une donnée de type string est une suite quelconque de caractères délimitée soit par des apostrophes (simple quotes), soit par des guillemets (double quotes), soit par des triples quotes (''' ou """).

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.

print("""1, " 2", \n 3,
4""")

Résultat :

1, " 2", 
 3,
4

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

Accès aux caractères individuels d'une chaîne[modifier | modifier le wikicode]

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 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.

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.

 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 :

>>> chaine = "Stéphanie"
>>> print(chaine[0], chaine[3])
S p


Taille des chaines[modifier | modifier le wikicode]

  • 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() :
>>> print(len(c))
29 #La chaîne de caractères 'c' contient 29 caractères !

>>> print(len('Zowerz'))
6

Sous-chaines[modifier | modifier le wikicode]

L'opérateur d'indiçage ([]) permet aussi de sélectionner des sous-chaines selon leurs indices. On appelle cette technique le slicing (« découpage en tranches »).

Dans la tranche [n,m], le nième caractère est inclus, mais pas le mième. Si vous voulez mémoriser aisément ce mécanisme, il faut vous représenter que les indices pointent des emplacements situés entre les caractères, comme dans le schéma ci-dessous :

illustration du système de numérotation des caractères

Au vu de ce schéma, il n'est pas difficile de comprendre que ch[3:7] extraira iett.

De plus, si la borne de départ est le premier caractère (indice 0) ou si celle d'arrivée est la dernière (indice égal à la longueur de la chaine), il devient facultatif. Exemple :

>>> chain = "123456789"
>>> print(chain[1:3])
23

>>> print(chain[0:-1])
12345678
>>> print(chain[:-1])
12345678

>>> print(chain[1:len(chain)])
23456789
>>> print(chain[1:])
23456789

Pour vérifier le début et la fin d'une chaine sans avoir à déterminer sur quelle longueur , on peut utiliser "startswith()" et "endswith()", mais c'est moins rapide car faisant appel à une fonction de plus haut niveau. (Référence nécessaire)

if chain.startswith('1234'):
    print('ok')
if chain.endswith('89'):
    print('ok')

Concaténation[modifier | modifier le wikicode]

L'opération d'assembler plusieurs petites chaînes pour en construire une plus grande s'appelle concaténation et on la réalise sous Python à l'aide de l'opérateur "+". Exemple :

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

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

>>> chaine = '8647'              
>>> print(chaine + 45)
   ==> *** erreur *** on ne peut pas additionner une chaîne et un nombre 

>>> print(int(chaine) + 65)
8712                         # OK : on peut additionner deux nombres

>>> print(chaine + str(65))
864765                       # OK : on peut concaténer deux chaines

Dans cet exemple, la fonction intégrée int() convertit la chaîne en nombre entier, et str() convertit l'entier en chaine.


Parcours d'une séquence : for... in...[modifier | modifier le wikicode]

Il arrive très souvent que l'on doive traiter l'intégralité d'une chaîne caractère par caractère, du premier jusqu'au dernier, pour effectuer à partir de chacun d'eux une opération quelconque. Nous appellerons cette opération un parcours. En nous limitant aux outils Python que nous connaissons déjà, nous pouvons envisager d'encoder un tel parcours sur la base de l'instruction while :

nom = 'Jacqueline'
index = 0
while index < len(nom):
    print(nom[index] + ' *'), 
    index = index + 1

Cette boucle « parcourt » donc la chaîne nom pour en extraire un à un tous les caractères, lesquels sont ensuite imprimés avec interposition d'astérisques. Notez bien que la condition utilisée avec l'instruction while est index < len(nom), ce qui signifie que le bouclage doit s'effectuer jusqu'à ce que l'on soit arrivé à l'indice numéro 9 (la chaîne compte en effet 10 caractères). Nous aurons effectivement traité tous les caractères de la chaîne, puisque ceux-ci sont indicés de zéro à 9.

Le parcours d'une séquence est une opération très fréquente en programmation. Pour en faciliter l'écriture, Python vous propose une structure de boucle plus appropriée, basée sur le couple d'instructions for ... in ... :

Avec ces instructions, le programme ci-dessus devient :

nom = 'Jacqueline'
for character in nom:
    print(character + ' *'),

Comme vous pouvez le constater, cette structure de boucle est plus compacte. Elle vous évite d'avoir à définir et à incrémenter une variable spécifique (un « compteur ») pour gérer l'indice du caractère que vous voulez traiter à chaque itération. La variable caract contiendra successivement tous les caractères de la chaîne, du premier jusqu'au dernier.

L'instruction for permet donc d'écrire des boucles, dans lesquelles l'itération traite successivement tous les éléments d'une séquence donnée. Dans l'exemple ci-dessus, la séquence était une chaîne de caractères. L'exemple ci-après démontre que l'on peut appliquer le même traitement aux listes :

liste = ['chien','chat','crocodile']
for animal in liste:
    print('longueur de la chaîne'), animal, '=', len(animal)

L'exécution de ce script donne :

longueur de la chaîne chien = 5
longueur de la chaîne chat = 4
longueur de la chaîne crocodile = 9

L'instruction for est un nouvel exemple d’instruction composée. N'oubliez donc pas le double point obligatoire à la fin de la ligne, et l'indentation du bloc d'instructions qui suit.

Le nom qui suit le mot réservé in est celui de la séquence qu'il faut traiter. Le nom qui suit le mot réservé for est celui que vous choisissez pour la variable destinée à contenir successivement tous les éléments de la séquence. Cette variable est définie automatiquement (c'est-à-dire qu'il est inutile de la définir au préalable), et son type est automatiquement adapté à celui de l'élément de la séquence qui est en cours de traitement.

Exemple :

divers = ['cheval', 3, 17.25, [5, 'Jean']]
for e in divers:
    print(e)

L'exécution de ce script donne :

cheval
3
17.25
[5, 'Jean']

Bien que les éléments de la liste divers soient tous de types différents (une chaîne de caractères, un entier, un réel, une liste), on peut affecter successivement leurs contenus à la variable e, sans qu'il s'ensuive des erreurs (ceci est rendu possible grâce au typage dynamique des variables Python).


Exercices

  1. Écrivez un script qui détermine si une chaîne contient ou non le caractère « e ».
  2. Écrivez un script qui compte le nombre d'occurrences du caractère « e » dans une chaîne.
  3. É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 »
  4. Écrivez un script qui recopie une chaîne (dans une nouvelle variable) en l'inversant.
    Ainsi par exemple, « zorglub » deviendra « bulgroz ».
  5. 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 ».

Solution

  1. # Recherche d'un caractère particulier dans une chaîne
    
    # Chaîne fournie au départ :
    chain = "Monty python flying circus"
    # Caractère à rechercher :
    letter = "e"
    # Recherche proprement dite :
    i = 0   # indice du caractère en cours d'examen
    found = False   # "drapeau" à lever si le caractère recherché est présent
    while i < len(chain):
        if chain[i] == letter:
            found = True
        i = i + 1
    
    # Affichage :
    print(u"Le caractère"), letter  # Le caractère e
    if t == 1:
        print(u"est présent")
    else:
        print(u"est introuvable")
    print(u"dans la chaîne"), chain  # dans la chaîne Monty python flying circus
    
  2. Réfléchissez !
  3. # Insertion d'un caractère d'espacement dans une chaîne
    
    # Chaîne fournie au départ :
    ch = "Gaston"
    # Caractère à insérer :
    cr = "*"
    # Le nombre de caractères à insérer est inférieur d'une unité au
    # nombre de caractères de la chaîne. On traitera donc celle-ci à
    # partir de son second caractère (en omettant le premier).
    lc = len(ch)    # nombre de caractères total
    i = 1           # indice du premier caractère à examiner (le second, en fait)
    nch = ch[0]     # nouvelle chaîne à construire (contient déjà le premier caractère)
    while i < lc:
        nch = nch + cr + ch[i]
        i = i + 1    
    # Affichage :
    print(nch)
    
  4. # Inversion d'une chaîne de caractères
    
    # Chaîne fournie au départ :
    ch = "zorglub"
    lc = len(ch)    # nombre de caractères total
    i = lc - 1      # le traitement commencera à partir du dernier caractère
    nch = ""        # nouvelle chaîne à construire (vide au départ)
    while i >= 0:
        nch = nch + ch[i]
        i = i - 1    
    # Affichage :
    print(nch)
    
  5. Réfléchissez !

Exercices

  1. Dans un conte américain, huit petits canetons s'appellent respectivement : Jack, Kack, Lack, Mack, Nack, Oack, Pack et Qack. Écrivez un script qui génère tous ces noms à partir des deux chaînes suivantes :
    • prefixes = 'JKLMNOP'
    • suffixe = 'ack'
    Si vous utilisez une instruction for... in... , votre script ne devrait comporter que deux lignes.
  2. Rechercher le nombre de mots contenus dans une phrase donnée.

Solution

  1. prefixes, suffixe = "JKLMNOP", "ack"
    
    for p in prefixes:
        print p + suffixe
    
  2.     # Comptage du nombre de mots dans "chain"
        chain = "Les petits ruisseaux font les grandes rivières"
        if len(chain) == 0:
            print(0)
        nm = 1                  # la chaîne comporte au moins un mot          
        for c in chain:
            if c == " ":        # il suffit de compter les espaces
                nm = nm + 1
        print(nm)
    

Appartenance d'un élément à une séquence : if.. in...[modifier | modifier le wikicode]

L'instruction in peut être utilisée indépendamment de for, pour vérifier si un élément donné fait partie ou non d'une séquence. Vous pouvez par exemple vous servir de in pour vérifier si tel caractère alphabétique fait partie d'un groupe bien déterminé :

car = "e"
voyelles = "aeiouyAEIOUY"
if car in voyelles:
    print car, "est une voyelle"

D'une manière similaire, vous pouvez vérifier l'appartenance d'un élément à une liste :

n = 5
nombrePremiers = [1, 2, 3, 5, 7, 11, 13, 17]
if  n in nombrePremiers:
    print n, "fait partie de notre liste de nombres premiers"

Cette instruction très puissante effectue donc à elle seule un véritable parcours de la séquence. À titre d'exercice, écrivez les instructions qui effectueraient le même travail à l'aide d'une boucle classique utilisant l'instruction while.

Exercices

  1. Écrivez un script qui affiche « vrai » si un caractère est un chiffre.
  2. Écrivez un script qui affiche « vrai » si un caractère est une majuscule.

Solution

        if character in "0123456789":
            print True
        else:
            print False
    
  1.     if character in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
            print True
        else:
            print False
    

Les chaînes sont des séquences non modifiables[modifier | modifier le wikicode]

Vous ne pouvez pas modifier le contenu d'une chaîne existante. En d'autres termes, vous ne pouvez pas utiliser l'opérateur [] dans la partie gauche d'une instruction d'affectation. Essayez par exemple d'exécuter le petit script suivant (qui cherche à remplacer une lettre dans une chaîne) :

salut = 'bonjour à tous'
salut[0] = 'B'
print salut

Au lieu d'afficher « Bonjour à tous », ce script « lève » une erreur du genre : TypeError: object doesn't support item assignment. Cette erreur est provoquée à la deuxième ligne du script. On y essaie de remplacer une lettre par une autre dans la chaîne, mais cela n'est pas permis.

Par contre, le script ci-dessous fonctionne :

salut = 'bonjour à tous'
salut = 'B' + salut[1:]
print salut

Dans cet autre exemple, en effet, nous ne modifions pas la chaîne "salut". Nous en recréons une nouvelle avec le même nom à la deuxième ligne du script (à partir d'un morceau de la précédente, soit, mais qu'importe : il s'agit bien d'une nouvelle chaîne).

Les chaînes sont comparables[modifier | modifier le wikicode]

Tous les opérateurs de comparaison dont nous avons parlé à propos des instructions de contrôle de flux (c'est-à-dire les instructions if ... elif ... else) fonctionnent aussi avec les chaînes de caractères. Cela vous sera très utile pour trier des mots par ordre alphabétique :

mot = raw_input("Entrez un mot quelconque : ")
if mot < "limonade":
    place = "précède"
elif mot > "limonade":
    place = "suit"
else:
    place = "se confond avec"
print "Le mot", mot, place, "le mot 'limonade' dans l'ordre alphabétique"

Ces comparaisons sont possibles, parce que les caractères alphabétiques qui constituent une chaîne de caractères sont mémorisés dans la mémoire de l'ordinateur sous forme de nombres binaires dont la valeur est liée à la place qu'occupe le caractère dans l'alphabet. Dans le système de codage ASCII, par exemple, A=65, B=66, C=67, etc.


Encodage[modifier | modifier le wikicode]

Pour encoder une chaine en Unicode, il faut la préfixer par la lettre "u"[1] :

>>> string = u"il était une fois"
>>> print(string)
'il était une fois'

Au sujet des chaînes de caractères, il est important de savoir que de notions différentes de chaînes de caractères existent en Python.

Pour des raisons historiques dans les versions de Python inférieures à Python 2, on considérait une chaîne de caractère comme une chaîne d'octets. Ceci permettait d'avoir un seul type pour traiter de deux notions différentes, mais pouvait parfois engendrer de la confusion sur le type traité.

  • Le type String contenait à la fois une séquence d'octet et une chaîne de caractères ASCII/UTF-8 (exemple : "Hello World").

Depuis la version 3 de Python, les types chaînes d'octet et chaîne de caractères sont clairement différenciées.

  • Le type chaîne de caractères (String) contient des caractères Unicode (exemple: 'xyzzy', "frobozz")
  • Les octets et tableaux d'octets (objets Bytes et bytearray) ne contiennent que des octets (l'un est immutable alors que l'autre est mutable). Exemple : b'xyzzy'.

Classement des caractères[modifier | modifier le wikicode]

Il est souvent utile de pouvoir déterminer si tel caractère extrait d'une chaîne est une lettre majuscule ou minuscule, ou plus généralement encore, de déterminer s'il s'agit bien d'une lettre, d'un chiffre, ou encore d'un autre caractère typographique.

Nous pouvons bien entendu écrire différentes fonctions pour assurer ces tâches. Une première possibilité consiste à utiliser l'instruction "in". Mais puisque nous savons désormais que les caractères forment une suite bien ordonnée dans le code ASCII, nous pouvons exploiter d'autres méthodes. Par exemple, pour déterminer si on a affaire à une minuscule :

    if 'a' <= character <= 'z' :
        print('bas de casse')
    else:
        print('haut de casse')

Exercices

  1. Écrivez un script qui affiche « vrai » si l'argument transmis est un chiffre (avec une autre méthode que celles exploitées précédemment)
  2. Écrivez un script qui affiche « vrai » si un caractère est une majuscule

Solution

  1.     if character >= "0" and character <= "9":
            print True
        else:
            print False
    
  2.     if character >= "A" and character <= "Z":
            print True
        else:
            print False
    

Afin que vous puissiez effectuer plus aisément toutes sortes de traitements sur les caractères, Python met à votre disposition un certain nombre de fonctions prédéfinies :

  • La fonction ord(character) accepte n'importe quel caractère comme argument. En retour, elle fournit le code ASCII correspondant à ce caractère. Ainsi ord('A') renvoie la valeur 65, et ord(u'é') 233.
  • La fonction chr(number) fait exactement le contraire. L'argument qu'on lui transmet doit être un entier compris entre 0 et 255. En retour, on obtient le caractère ASCII correspondant. Ainsi chr(65) renvoie le caractère A.

Exercices

  1. Écrivez un petit script qui affiche une table des codes ASCII. Le programme doit afficher tous les caractères en regard des codes correspondants. A partir de cette table, établissez les relations numériques reliant chaque caractère majuscule à chaque caractère minuscule.
  2. À partir des relations trouvées, écrivez un script qui convertit tous les caractères d'une phrase donnée en capitales.
  3. À partir des mêmes relations, écrivez un script qui convertit tous les caractères d'une phrase en capitales.
  4. Écrivez un script qui compte le nombre de fois qu'apparaît tel caractère (fourni en argument) dans une phrase donnée.
  5. Écrivez un script qui affiche le nombre de voyelles contenues dans une phrase donnée.

Solution

  1. # Table des codes ASCII :
    c = 32          # Premier code ASCII <imprimable>
    while c < 128 : # caractères non accentués seulement 
        print("Code"), c, ":", chr(c), "  ",
        c = c + 1
    
  2. Réfléchissez !
  3. # Convertir majuscules -> minuscules et inversement :
        # Échange les majuscules et les minuscules de "chaine"
        chain = "Ferdinand-Charles de CAMARET"
        newChain = ""                   # chaîne à construire
        for car in chain:
            code = ord(car)
            if car >= "A" and car <= "Z":
                code = code + 32
            elif car >= "a" and car <= "z":
                code = code - 32
            newChain = newChain + chr(code)
        print(newChain)
    
  4. Réfléchissez !
  5. # Comptage de voyelles :
        # Teste si car est une voyelle"
        if character in "AEIOUYaeiouy":
            print(True)
        else:
            print(False)
    
        # Compte les voyelles présentes dans la chaîne "chaine"
        n = 0
        for c in chaine:
            if voyelle(c):
                n = n + 1
        print(n)
    

Méthodes des objets string[modifier | modifier le wikicode]

Sous Python, les chaînes de caractères sont des objets. On peut donc effectuer de nombreux traitements dessus en utilisant des méthodes appropriées. En voici quelques-unes, choisies parmi les plus utiles. Mais vous pouvez obtenir la liste complète de toutes les méthodes associées à un objet à l'aide de la fonction intégrée dir() ou help(str) :

>>> dir('')
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
  • Les fonctions "str()" et "repr()" (pour représentation d'objet) permettent de transformer un objet Python quelconque en chaîne de caractères. Ces deux fonctions sont différentes : "str('chaine')" retournera 'chaine' tandis que "repr('chaine')" retournera "'chaine'".
  • index(c) : retrouve l'index de la première occurrence du caractère "c" dans la chaîne, ou déclenche une erreur si absent (ValueError: substring not found).
>>> foin = "Portez ce vieux whisky au juge blond qui fume"
>>> print foin.index("w")
16
  • find(aiguille) : cherche la position d'une sous-chaîne aiguille dans la chaîne, en partant du début.
>>> foin = "Cette leçon vaut bien un fromage, sans doute ?"
>>> aiguille = "fromage"
>>> print foin.find(aiguille)
25
  • rfind(aiguille) : pareil que "find" mais en partant de la fin (reverse).
>>> foin = "Cette leçon vaut bien deux fromages, dont un fromage râpé ?"
>>> aiguille = "fromage"
>>> print foin.rfind(aiguille)
46
  • count(aiguille) : compte le nombre de sous-chaînes aiguille dans la chaîne.
>>> foin = "Le héron au long bec emmanché d'un long cou"
>>> aiguille = 'long'
>>> print foin.count(aiguille)
2
  • lower() : convertit une chaîne en minuscules.
>>> phrase ="ATTENTION : Danger !"
>>> print phrase.lower()
attention : danger !
  • upper() : convertit une chaîne en majuscules.
>>> phrase = "Merci beaucoup"
>>> print phrase.upper()
MERCI BEAUCOUP
  • capitalize() : convertit en majuscule la première lettre d'une chaîne.
>>> phrase = "quel beau temps, aujourd'hui !"
>>> print phrase.capitalize()
"Quel beau temps, aujourd'hui !"
  • swapcase() : convertit toutes les majuscules en minuscules et vice-versa.
>>> phrase = "La CIGALE et la FOURMI"
>>> print phrase.swapcase()
lA cigale ET LA fourmi
  • strip() : enlève les espaces éventuels au début et à la fin de la chaîne (trime).
>>> phrase = "   Monty Python   "
>>> phrase.strip()
'Monty Python'
  • replace(old, new) : remplace tous les caractères old par des caractères new dans la chaîne.
>>> phrase = "Si ce n'est toi c'est donc ton frère"
>>> print phrase.replace(" ","_")
Si_ce_n'est_toi_c'est_donc_ton_frère


Dans la plupart de ces méthodes, il est possible de préciser quelle portion de la chaîne doit être traitée, en ajoutant des arguments supplémentaires.

>>> print ch9.index("e")		# cherche à partir du début de la chaîne 
4							# et trouve le premier 'e'
>>> print ch9.index("e",5)		# cherche seulement à partir de l'indice 5
8							# et trouve le second 'e'
>>> print ch9.index("e",15)		# cherche à partir du caractère n° 15
29							# et trouve le quatrième 'e'

Références[modifier | modifier le wikicode]


Listes

Déclaration[modifier | modifier le wikicode]

Les listes sont des séquences, des collections ordonnées d'objets séparés par des virgules. On les déclare avec l'opérateur d'indiçage ([]) :

>> maListe = ['a','b','c']
>> maListe
['a','b','c']

Lecture[modifier | modifier le wikicode]

Comme les caractères dans une chaîne, les objets placés dans une liste sont rendus accessibles par l'intermédiaire d'un index (un nombre qui indique l'emplacement de l'objet dans la séquence, à partir de zéro). De plus, le slicing (« découpage en tranches ») permet aussi de dégager une sous-liste en précisant deux index correspondant aux bornes de la plage.

Une sortie indicée donne :

>> maListe[0]
'a'

>> maListe[-1]
'c'

Une séquence donne par slicing :

>> maListe[0:2]
['a','b']

>> maListe[1:]
['b','c']

Types[modifier | modifier le wikicode]

Les éléments qui constituent une liste peuvent être de types variés :

>>> jour = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 476, 3.142]
>>> print(jour)
['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 476, 3.142]

Dans cet exemple, en effet, les premiers éléments sont des chaînes de caractères, puis il y a un entier et un réel. A cet égard, le concept de liste est donc différent des tableaux (array) que l'on rencontre les langages de programmation de bas niveau, où tous les éléments doivent être du même type.

Recherche[modifier | modifier le wikicode]

Vous pouvez aisément déterminer si un élément fait partie d'une liste à l'aide de l'instruction in :

 print("a" in ["a", "b", "c"])      # True
 print(not "a" in ["a", "b", "c"])  # False

Si l'emplacement de l'élément importe dans la liste :

 print ["a", "b", "c"].index("a") == 0 # True
 print ["a", "b", "c"].index("z")      # ValueError

Modification[modifier | modifier le wikicode]

Affectation[modifier | modifier le wikicode]

À la différence de ce qui se passe pour les chaînes, qui constituent un type de données non-modifiables, il est possible de changer les éléments individuels d'une liste :

>>> jour = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 476, 3.142]
>>> jour[5] = jour[5] + 1016
>>> print(jour)
['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 1492, 3.142]

Les exemples ci-dessus devraient attirer votre attention sur le fait qu'une tranche découpée dans une liste est toujours elle-même une liste (même s'il s'agit d'une tranche qui ne contient qu'un seul élément), alors qu'un élément isolé peut contenir n'importe quel type de donnée.

Exemple en deux dimensions :

>>> jour = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', ['samedi matin', 'samedi après-midi', 'samedi soir'], 'dimanche']
>>> jour[5][0] = "samedi midi"
>>> jour
>>> jour = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', ['samedi midi', 'samedi après-midi', 'samedi soir'], 'dimanche']

Ainsi, dans l'exemple ci-dessus on remplace le premier élément d'une liste (n° 0), qui est elle-même l'élément n° 5 d'une autre liste.

Opérations[modifier | modifier le wikicode]

On peut appliquer aux listes les opérateurs + (concaténation) et * (multiplication) :

>>> fruits = ['orange','citron']
>>> legumes = ['poireau','oignon','tomate']
>>> fruits + legumes
['orange', 'citron', 'poireau', 'oignon', 'tomate']
>>> fruits * 3
['orange', 'citron', 'orange', 'citron', 'orange', 'citron']

L'opérateur * est particulièrement utile pour créer une liste de "n" éléments identiques :

>>> sept_zeros = [0]*7
>>> sept_zeros
[0, 0, 0, 0, 0, 0, 0]

Techniques de slicing avancées pour modifier une liste[modifier | modifier le wikicode]

Insertion[modifier | modifier le wikicode]

Insertion d'un ou plusieurs éléments n'importe où dans une liste :

>>> mots = ['jambon', 'fromage', 'confiture', 'chocolat']
>>> mots[2:2] = ["miel"]
>>> mots
['jambon', 'fromage', 'miel', 'confiture', 'chocolat']
>>> mots[5:5] = ['saucisson', 'ketchup']
>>> mots
['jambon', 'fromage', 'miel', 'confiture', 'chocolat', 'saucisson', 'ketchup']

Pour utiliser cette technique, vous devez prendre en compte les particularités suivantes :

  • Si vous utilisez l'opérateur [ ] à la gauche du signe égale pour effectuer une insertion ou une suppression d'élément(s) dans une liste, vous devez obligatoirement y indiquer une « tranche » dans la liste cible (c'est-à-dire deux index réunis par le symbole ":"), et non un élément isolé dans cette liste.
  • L'élément que vous fournissez à la droite du signe égale doit lui-même être une liste. Si vous n'insérez qu'un seul élément, il vous faut donc le présenter entre crochets pour le transformer d'abord en une liste d'un seul élément. Notez bien que l'élément mots[1] n'est pas une liste (c'est la chaîne fromage), alors que l'élément mots[1:3] en est une.

Suppression[modifier | modifier le wikicode]

Suppression / remplacement d'éléments :

1 >>> mots[2:5] = []                       # [] désigne une liste vide
2 >>> mots
3 ['jambon','fromage','saucisson', 'ketchup']
4 >>> mots[1:3] = ['salade']
5 >>> mots
6 ['jambon', 'salade', 'ketchup']
7 >>> mots[1:] = ['mayonnaise', 'poulet', 'tomate']
8 >>> mots
9 ['jambon', 'mayonnaise', 'poulet', 'tomate']
  • À la première ligne de cet exemple, nous remplaçons la tranche [2:5] par une liste vide, ce qui correspond à un effacement.
  • À la quatrième ligne, nous remplaçons une tranche par un seul élément. (Notez encore une fois que cet élément doit lui-même être « présenté » comme une liste).
  • À la 7e ligne, nous remplaçons une tranche de deux éléments par une autre qui en comporte 3.

Différence[modifier | modifier le wikicode]

Pour obtenir la différence entre deux listes :

a = ['jambon','fromage','saucisson', 'ketchup']
b = ['jambon', 'mayonnaise', 'poulet', 'tomate']
print [item for item in a if item not in b]
# ['fromage', 'saucisson', 'ketchup']

Intersection[modifier | modifier le wikicode]

Pour l'intersection entre deux listes (en préservant l'ordre des éléments y compris leurs doublons), on applique la différence de la différence :

a = ['jambon','fromage','saucisson', 'ketchup']
b = ['jambon', 'mayonnaise', 'poulet', 'tomate']
dif = [item for item in a if item not in b]
print [item for item in a if item not in dif]
# ['jambon']

Copie[modifier | modifier le wikicode]

Considérons que vous disposez d'une liste fable que vous souhaitez recopier dans une nouvelle variable que vous appellerez phrase. La première idée qui vous viendra à l'esprit sera certainement d'écrire une simple affectation telle que :

>>> phrase = fable

En procédant ainsi, sachez que vous ne créez pas une véritable copie. À la suite de cette instruction, il n'existe toujours qu'une seule liste dans la mémoire de l'ordinateur. Ce que vous avez créé est seulement une nouvelle référence vers cette liste. Essayez par exemple :

>>> fable = ['Je','plie','mais','ne','romps','point']
>>> phrase = fable
>>> fable[4] ='casse'
>>> phrase
['Je', 'plie', 'mais', 'ne', 'casse', 'point']

Si la variable phrase contenait une véritable copie de la liste, cette copie serait indépendante de l'original et ne devrait donc pas pouvoir être modifiée par une instruction telle que celle de la troisième ligne, qui s'applique à la variable fable. Vous pouvez encore expérimenter d'autres modifications, soit au contenu de fable, soit au contenu de phrase. Dans tous les cas, vous constaterez que les modifications de l'une sont répercutées dans l'autre, et vice-versa.

En fait, les noms fable et phrase désignent tous deux un seul et même objet en mémoire. Pour décrire cette situation, les informaticiens diront que le nom phrase est un alias du nom fable.

shéma de la copie d'une liste

Nous verrons plus tard l'utilité des alias. Pour l'instant, nous voudrions disposer d'une technique pour effectuer une véritable copie d'une liste. Avec les notions vues précédemment, vous devriez pouvoir en trouver une par vous-même.

 python vous autorise à « étendre » une longue instruction sur plusieurs lignes, si vous continuez à encoder quelque chose qui est délimité par une paire de parenthèses, de crochets ou d'accolades. Vous pouvez traiter ainsi des expressions parenthésées, ou encore la définition de longues listes, de grands tuples ou de grands dictionnaires. Le niveau d'indentation n'a pas d'importance : l'interpréteur détecte la fin de l'instruction, là où la paire syntaxique est refermée.

Cette fonctionnalité vous permet d'améliorer la lisibilité de vos programmes. Exemple :

couleurs = ['noir', 'brun', 'rouge',
            'orange', 'jaune', 'vert',
            'bleu', 'violet', 'gris', 'blanc']


Méthodes[modifier | modifier le wikicode]

Sous Python, les listes sont des objets à part entière, et vous pouvez donc leur appliquer un certain nombre de méthodes particulièrement efficaces, après l'opérateur "." :

>>> nombres = [17, 38, 10, 25, 72]

>>> nombres.sort()                 # trier la liste
>>> nombres
[10, 17, 25, 38, 72]

>>> nombres.append(12)             # ajouter un élément à la fin
>>> nombres
[10, 17, 25, 38, 72, 12]

>>> nombres.reverse()              # inverser l'ordre des éléments
>>> nombres
[12, 72, 38, 25, 17, 10]

>>> nombres.index(17)              # retrouver l'index d'un élément
4

>>> nombres.remove(38)             # enlever (effacer) un élément
>>> nombres
[12, 72, 25, 17, 10]

append[modifier | modifier le wikicode]

append() (ajouter) : l'exemple suivant qui fait appel à la méthode "append" de l'objet "liste" (déclarée vide) illustre ce concept.

Il s'agit de remplir la hotte du Père Noël.

 #!/usr/bin/python
 # -*- coding: iso8859-1 -*-
 
 # on prépare une liste encore vide
 cadeaux = []
 
 # on va ajouter des éléments à la liste
 unCadeau = ""
 
 # la suite des éléments à introduire dans la liste est définie par l'utilisateur
 # lorsqu'il a terminé, l'utilisateur indique le mot "fin" qui ne sera pas introduit dans la liste
 while unCadeau <> "fin":
 	unCadeau = raw_input ("Père Noël, je voudrais que tu m'apportes ")
        # si l'utilisateur n'a pas frappé "fin", le mot est ajouté à la liste
 	if unCadeau <> "fin":
 		cadeaux.append(unCadeau)
 
 # finalement, on écrit la suite des éléments introduits dans la liste
 for chaqueCadeau in cadeaux:
 	print chaqueCadeau

split[modifier | modifier le wikicode]

split() : convertit une chaîne en une liste de sous-chaînes. On peut choisir le caractère séparateur en le fournissant comme argument, sinon c'est un espace, par défaut.

>>> chaine ="Votez pour moi"
>>> tableau = chaine.split()
>>> print tableau
['Votez', 'pour', 'moi']

>>> chaine = "Cet exemple, parmi d'autres, peut encore servir"
>>> chaine.split(",")
['Cet exemple', " parmi d'autres", ' peut encore servir']

join[modifier | modifier le wikicode]

join(liste) : rassemble une liste de chaînes en une seule (Cette méthode fait donc l'inverse de la précédente). Attention : la chaîne à laquelle on applique cette méthode est celle qui servira de séparateur (un ou plusieurs caractères) ; l'argument transmis est la liste des chaînes à rassembler.

>>> tableau = ["Salut", "les", "copains"]
>>> print  " ".join(tableau)
Salut les copains
>>> print  "___".join(tableau)
Salut___les___copains

pop[modifier | modifier le wikicode]

pop(i) retire et renvoie l'élément de la liste d'index i. Si i est vide, il traite le dernier élément.

>>> list = [1, 2, 3, 4]

>>> print(list.pop(0))
1
>>> list
[2, 3, 4]

>>> print(list.pop())
4
>>>list
[2, 3]


Fonctions[modifier | modifier le wikicode]

len[modifier | modifier le wikicode]

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 :

>>> len(jour)
7

Supposons par exemple que vous voulez créer une liste B qui contienne le même nombre d'éléments qu'une autre liste A. Vous pouvez obtenir ce résultat de différentes manières, mais l'une des plus simples consistera à effectuer : B = [0]*len(A).

del[modifier | modifier le wikicode]

Une autre fonction intégrée permet de supprimer d'une liste un élément ou plusieurs éléments quelconques à partir de leurs index. Il s'agit de la fonction del() :

>>> jour = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 476, 3.142]

>>> del(jour[5:7])
>>> print(jour)
['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi']

>>> del(jour[0])
>>> print(jour)
['mardi', 'mercredi', 'jeudi', 'vendredi']
 notez bien la différence entre la méthode remove() et la fonction del() : del travaille avec un indice ou une tranche d'indices, tandis que remove() recherche une valeur (si plusieurs éléments de la liste possèdent la même valeur, seul le premier est effacé).

min et max[modifier | modifier le wikicode]

  • min(liste) : minimum d'une liste (élément ayant la plus petite valeur).
  • max(liste) : maximum d'une liste.
>>> jour = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi']

>>> min(jour)
'jeudi'

>>> max(jour)
'vendredi'

range[modifier | modifier le wikicode]

Si vous devez manipuler des séquences de nombres, vous pouvez les créer très aisément à l'aide de cette fonction :

>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Sous python 3.6: print(list(range(10))) La fonction range() génère une liste de nombres entiers de valeurs croissantes. Si vous appelez range() avec un seul argument, la liste contiendra un nombre de valeurs égal à l'argument fourni, mais en commençant à partir de zéro (c'est-à-dire que range(n) génère les nombres de 0 à n-1).

Notez bien que l'argument fourni n'est jamais dans la liste générée.

On peut aussi utiliser range() avec deux, ou même trois arguments séparés par des virgules, afin de générer des séquences de nombres plus spécifiques :

>>> range(5,13)
[5, 6, 7, 8, 9, 10, 11, 12]
>>> range(3,16,3)
[3, 6, 9, 12, 15]

Si vous avez du mal à assimiler l'exemple ci-dessus, considérez que range() attend toujours trois arguments, que l'on pourrait intituler FROM, TO et STEP. FROM est la première valeur à générer, TO est la dernière (ou plutôt la dernière + un), et STEP le « pas » à sauter pour passer d'une valeur à la suivante. S'ils ne sont pas fournis, les paramètres FROM et STEP prennent leurs valeurs par défaut, qui sont respectivement 0 et 1.

Parcours d'une liste à l'aide de for, range() et len()[modifier | modifier le wikicode]

L'instruction for est l'instruction idéale pour parcourir une liste :

>>> prov = ['La','raison','du','plus','fort','est','toujours','la','meilleure']
>>> for mot in prov:
       print mot,
La raison du plus fort est toujours la meilleure

Il est très pratique de combiner les fonctions range() et len() pour obtenir automatiquement tous les indices d'une séquence (liste ou chaîne). Exemple :

fable = ['Maître','Corbeau','sur','un','arbre','perché']
for index in range(len(fable)):
    print index, fable[index]

Mais il existe également une syntaxe adaptée à cela :

for (cle, valeur) in enumerate(fable): {retour à la ligne}{tab}print cle, valeur

L'exécution de ce script donne le résultat :

0 Maître
1 Corbeau
2 sur
3 un
4 arbre
5 perché

Tableau à trois lignes :

monTableau = range(1, 5)
monTableau[1] = u'ligne 1'
monTableau[2] = u'ligne 2'
monTableau[3] = u'ligne 3'

for ligne in range(1, 4):
    print(monTableau[ligne])

Tableau à deux dimensions :

ligne = 3
colonne = 2
monTableau = [[0] * (colonne+1) for _ in range(ligne+1)]
monTableau[1][1] = u'1.1'
monTableau[1][2] = u'1.2'
monTableau[2][1] = u'2.1'
monTableau[2][2] = u'2.2'
monTableau[3][1] = u'3.1'
monTableau[3][2] = u'3.2'

for l in range(1, ligne + 1):
    for c in range(1, colonne + 1):
        print(monTableau[l][c])

Une conséquence du typage dynamique[modifier | modifier le wikicode]

Le type de la variable utilisée avec l'instruction "for" est redéfini continuellement au fur et à mesure du parcours : même si les éléments d'une liste sont de types différents, on peut parcourir cette liste à l'aide de "for" sans qu'il ne s'ensuive une erreur, car le type de la variable de parcours s'adapte automatiquement à celui de l'élément en cours de lecture. Exemple :

>>> divers = [3, 17.25, [5, 'Jean'], 'Linux is not Windoze']
>>> for item in divers:
        print item, type(item)
3 <type 'int'>
17.25 <type 'float'>
[5, 'Jean'] <type 'list'>
Linux is not Windoze <type 'str'>

random[modifier | modifier le wikicode]

La plupart des programmes d'ordinateur font exactement la même chose chaque fois qu'on les exécute. De tels programmes sont dits déterministes. Le déterminisme est certainement une bonne chose : nous voulons évidemment qu'une même série de calculs appliquée aux mêmes données initiales aboutisse toujours au même résultat. Pour certaines applications, cependant, nous pouvons souhaiter que l'ordinateur soit imprévisible. Le cas des jeux constitue un exemple évident, mais il en existe bien d'autres.

Contrairement aux apparences, il n'est pas facile du tout d'écrire un algorithme qui soit réellement non-déterministe (c'est-à-dire qui produise un résultat totalement imprévisible). Il existe cependant des techniques mathématiques permettant de simuler plus ou moins bien l'effet du hasard. Des livres entiers ont été écrits sur les moyens de produire ainsi un hasard « de bonne qualité ». Nous n'allons évidemment pas développer ici une telle question, mais rien ne vous empêche de consulter à ce sujet votre professeur de mathématiques.

Dans son module random, Python propose toute une série de fonctions permettant de générer des nombres aléatoires qui suivent différentes distributions mathématiques. Nous n'examinerons ici que quelques-unes d'entre elles. Veuillez consulter la documentation en ligne pour découvrir les autres. Vous pouvez importer toutes les fonctions du module par :

>>> from random import *

Pour créer une liste de nombres réels aléatoires, de valeur comprise entre zéro et un :

>>> s = [0]*tailleListe
    for i in range(tailleListe):
        s[i] = random()
    print(s)

Vous pouvez constater que nous avons pris le parti de construire d'abord une liste de zéros de taille n, et ensuite de remplacer les zéros par des nombres aléatoires.

Exercices

  1. Réécrivez la fonction list_aleat() ci-dessus, en utilisant la méthode append() pour construire la liste petit à petit à partir d'une liste vide (au lieu de remplacer les zéros d'une liste préexistante comme nous l'avons fait).
  2. Écrivez une fonction imprime_liste() qui permette d'afficher ligne par ligne tous les éléments contenus dans une liste de taille quelconque. Le nom de la liste sera fourni en argument. Utilisez cette fonction pour imprimer la liste de nombres aléatoires générés par la fonction list_aleat(). Ainsi par exemple, l'instruction imprime_liste(liste_aleat(8)) devra afficher une colonne de 8 nombres réels aléatoires.

Solution

  1. Réfléchissez !
  2. Réfléchissez !

Les nombres ainsi générés sont-ils vraiment aléatoires ? C'est difficile à dire. Si nous ne tirons qu'un petit nombre de valeurs, nous ne pouvons rien vérifier. Par contre, si nous utilisons un grand nombre de fois la fonction random(), nous nous attendons à ce que la moitié des valeurs produites soient plus grandes que 0,5 (et l'autre moitié plus petites).

Affinons ce raisonnement. Les valeurs tirées sont toujours dans l'intervalle 0-1. Partageons cet intervalle en 4 fractions égales : de 0 à 0,25 , de 0,25 à 0,5 , de 0,5 à 0,75 , et de 0,75 à 1. Si nous tirons un grand nombre de valeurs au hasard, nous nous attendons à ce qu'il y en ait autant qui se situent dans chacune de nos 4 fractions. Et nous pouvons généraliser ce raisonnement à un nombre quelconque de fractions, du moment qu'elles soient égales.

Exercices

  1. Vous allez écrire un programme destiné à vérifier le fonctionnement du générateur de nombres aléatoires de Python en appliquant la théorie exposée ci-dessus. Votre programme devra donc : a) Demander à l'utilisateur le nombre de valeurs à tirer au hasard à l'aide de la fonction random(). Il serait intéressant que le programme propose un nombre par défaut (1000 par exemple). b) Demander à l'utilisateur en combien de fractions il souhaite partager l'intervalle des valeurs possibles (c'est-à-dire l'intervalle de 0 à 1). Ici aussi, il faudrait proposer un nombre de par défaut (5 fractions, par exemple). Vous pouvez également limiter le choix de l'utilisateur à un nombre compris entre 2 et le 1/10e du nombre de valeurs tirées au hasard. c) Construire une liste de N compteurs (N étant le nombre de fractions souhaitées). Chacun d'eux sera évidemment initialisé à zéro. d) Tirer au hasard toutes les valeurs demandées, à l'aide de la fonction random(), et mémoriser ces valeurs dans une liste. e) Mettre en œuvre un parcours de la liste des valeurs tirées au hasard (boucle), et effectuer un test sur chacune d'elles pour déterminer dans quelle fraction de l'intervalle 0-1 elle se situe. Incrémenter de une unité le compteur correspondant. f) Lorsque c'est terminé, afficher l'état de chacun des compteurs.

Solution

  1. # Test du générateur de nombres aléatoires :
    from random import random           # tire au hasard un réel entre 0 et 1
    
    n = raw_input("Nombre de valeurs à tirer au hasard (défaut = 1000) : ")
    if n == "":
        nVal =1000
    else:
        nVal = int(n)
    
    n = raw_input("Nombre de fractions dans l'intervalle 0-1 (entre 2 et "
                  + str(nVal/10) + ", défaut =5) : ")
    if n == "":
        nFra =5
    else:
        nFra = int(n)
    
    if nFra < 2:
        nFra =2
    elif nFra > nVal/10:
        nFra = nVal/10
    
    print "Tirage au sort des", nVal, "valeurs ..."
    listVal = [0]*nVal                      # créer une liste de zéros
    for i in range(nVal):                   # puis modifier chaque élément
        listVal[i] = random()
    
    print "Comptage des valeurs dans chacune des", nFra, "fractions ..."
    listCompt = [0]*nFra                    # créer une liste de compteurs
    
    # parcourir la liste des valeurs :
    for valeur in listVal:
        # trouver l'index de la fraction qui contient la valeur :    
        index = int(valeur*nFra)
        # incrémenter le compteur correspondant :
        listCompt[index] = listCompt[index] +1
    
    # afficher l'état des compteurs :
    for compt in listCompt:
        print compt,
    

Exemple de résultats affichés par un programme de ce type[modifier | modifier le wikicode]

Nombre de valeurs à tirer au hasard (défaut = 1000) : 100
Nombre de fractions dans l'intervalle 0-1 (entre 2 et 10, défaut =5) : 5
Tirage au sort des 100 valeurs ...
Comptage des valeurs dans chacune des 5 fractions ...
11 30 25 14 20 
Nombre de valeurs à tirer au hasard (défaut = 1000) : 10000
Nombre de fractions dans l'intervalle 0-1 (entre 2 et 1000, défaut =5) : 5
Tirage au sort des 10000 valeurs ...
Comptage des valeurs dans chacune des 5 fractions ...
1970 1972 2061 1935 2062

Une bonne approche de ce genre de problème consiste à essayer d'imaginer quelles fonctions simples vous pourriez écrire pour résoudre l'une ou l'autre partie du problème, puis de les utiliser dans un ensemble plus vaste.

Par exemple, vous pourriez chercher à définir d'abord une fonction numeroFraction() qui servirait à déterminer dans quelle fraction de l'intervalle 0-1 une valeur tirée se situe. Cette fonction attendrait deux arguments (la valeur tirée, le nombre de fractions choisi par l'utilisateur) et fournirait en retour l'index du compteur à incrémenter (c'est-à-dire le n° de la fraction corres-pondante). Il existe peut-être un raisonnement mathématique simple qui permette de déterminer l'index de la fraction à partir de ces deux arguments. Pensez notamment à la fonction intégrée int(), qui permet de convertir un nombre réel en nombre entier en éliminant sa partie décimale.

Si vous ne trouvez pas, une autre réflexion intéressante serait peut-être de construire d'abord une liste contenant les valeurs « pivots » qui délimitent les fractions retenues (par exemple 0 – 0,25 – 0,5 – 0,75 - 1 dans le cas de 4 fractions). La connaissance de ces valeurs faciliterait peut-être l'écriture de la fonction numeroFraction() que nous souhaitons mettre au point.

Si vous disposez d'un temps suffisant, vous pouvez aussi réaliser une version graphique de ce programme, qui présentera les résultats sous la forme d'un histogramme (diagramme « en bâtons »).

Tirage au hasard de nombres entiers[modifier | modifier le wikicode]

Lorsque vous développerez des projets personnels, il vous arrivera fréquemment de souhaiter pouvoir disposer d'une fonction qui permette de tirer au hasard un nombre entier entre certaines limites. Par exemple, si vous voulez écrire un programme de jeu dans lequel des cartes à jouer sont tirées au hasard (à partir d'un jeu ordinaire de 52 cartes), vous aurez certainement l'utilité d'une fonction capable de tirer au hasard un nombre entier compris entre 1 et 52.

Vous pouvez pour ce faire utiliser la fonction randrange() du module random.

Cette fonction peut être utilisée avec 1, 2 ou 3 arguments.

Avec un seul argument, elle renvoie un entier compris entre zéro et la valeur de l'argument diminué d'une unité. Par exemple, randrange(6) renvoie un nombre compris entre 0 et 5.

Avec deux arguments, le nombre renvoyé est compris entre la valeur du premier argument et la valeur du second argument diminué d'une unité. Par exemple, randrange(2, 8) renvoie un nombre compris entre 2 et 7.

Si l'on ajoute un troisième argument, celui-ci indique que le nombre tiré au hasard doit faire partie d'une série limitée d'entiers, séparés les uns des autres par un certain intervalle, défini lui-même par ce troisième argument. Par exemple, randrange(3, 13, 3) renverra un des nombres de la série 3, 6, 9, 12 :

>>> for i in range(15):
        print random.randrange(3,13,3),

3 12 6 9 6 6 12 6 3 6 9 3 6 12 12

Exercices

  1. Écrivez un script qui tire au hasard des cartes à jouer. Le nom de la carte tirée doit être correctement présenté, « en clair ». Le programme affichera par exemple : Frappez <Enter> pour tirer une carte :
    Dix de Trèfle
    Frappez <Enter> pour tirer une carte :
    As de Carreau
    Frappez <Enter> pour tirer une carte :
    Huit de Pique
    Frappez <Enter> pour tirer une carte :
    etc ...

Solution

  1. # Tirage de cartes
    from random import randrange
    
    couleurs = ['Pique', 'Trèfle', 'Carreau', 'Coeur']
    valeurs = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'valet', 'dame', 'roi', 'as']
    
    # Construction de la liste des 52 cartes :
    carte =[]
    for coul in couleurs:
         for val in valeurs:
              carte.append("%s de %s" % (str(val), coul))
    
    # Tirage au hasard :
    while 1:
         k = raw_input("Frappez <c> pour tirer une carte, <Enter> pour terminer ") 
         if k =="":
              break
         r = randrange(52)
         print carte[r]
    

map[modifier | modifier le wikicode]

Permet d'appliquer une fonction à toutes les entrées d'une liste. Par exemple pour les trimer :

l = [' ma super ligne 1\n', ' ma super ligne 2\n']
l = map(str.strip, l)
print l
# ['ma super ligne 1', 'ma super ligne 2']

Exercices[modifier | modifier le wikicode]

Exercices

  1. 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 insère dans la seconde liste tous les éléments de la première, de telle sorte que chaque nom de mois soit suivi du nombre de jours correspondant : ['Janvier',31,'Février',28,'Mars',31, etc...].
  2. Créez une liste A contenant quelques éléments. Effectuez une vraie copie de cette liste dans une nouvelle variable B. Suggestion : créez d'abord une liste B de même taille que A mais ne contenant que des zéros. Remplacez ensuite tous ces zéros par les éléments tirés de A.
  3. Même question, mais autre suggestion : créez d'abord une liste B vide. Remplissez-la ensuite à l'aide des éléments de A ajoutés l'un après l'autre.
  4. Même question, autre suggestion encore : pour créer la liste B, découpez dans la liste A une tranche incluant tous les éléments (à l'aide de l'opérateur [:]).
  5. Un nombre premier est un nombre qui n'est divisible que par un et par lui-même. Écrivez un programme qui établisse la liste de tous les nombres premiers compris entre 1 et 1000, en utilisant la méthode du crible d'Ératosthène :
    • Créez une liste de 1000 éléments, chacun initialisé à la valeur 1.
    • Parcourez cette liste à partir de l'élément d'indice 2 : si l'élément analysé possède la valeur 1, mettez à zéro tous les autres éléments de la liste, dont les indices sont des multiples entiers de l'indice auquel vous êtes arrivé.
    Lorsque vous aurez parcouru ainsi toute la liste, les indices des éléments qui seront restés à 1 seront les nombres premiers recherchés. En effet : A partir de l'indice 2, vous annulez tous les éléments d'indices pairs : 4, 6, 8, 10, etc. Avec l'indice 3, vous annulez les éléments d'indices 6, 9, 12, 15, etc., et ainsi de suite. Seuls resteront à 1 les éléments dont les indices sont effectivement des nombres premiers.

Solution

  1. # Insertion de nouveaux éléments dans une liste existante
    
    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']
    
    c, d = 1, 0
    while d < 12 :
         t2[c:c] = [t1[d]]       # ! l'élément inséré doit être une liste
         c, d = c+2, d+1
    </pre>
    </li>
    
    <li>Réfléchissez !</li>
    
    <li>Réfléchissez !</li>
    
    <li>Réfléchissez !</li>
    
    <li>
    <source lang=python>
    # Crible d’Ératosthène pour rechercher les nombres premiers de 1 à 999
    
    # Créer une liste de 1000 éléments 1 (leurs indices vont de 0 à 999) :
    lst = [1]*1000           
    # Parcourir la liste à partir de l'élément d'indice 2:
    for i in range(2,1000):
        # Mettre à zéro les éléments suivants dans la liste,
        # dont les indices sont des multiples de i :
        for j in range(i*2, 1000, i):
            lst[j] = 0
    
    # Afficher les indices des éléments restés à 1 (on ignore l'élément 0) :
    for i in range(1,1000):
        if lst[i]:
            print i,
    

Exercices

  1. Déterminez vous-même ce qui se passe lorsque l'un ou l'autre des indices de découpage est erroné, et décrivez cela le mieux possible (si le second indice est plus petit que le premier, par exemple, ou bien si le second indice est plus grand que la taille de la chaîne).
  2. Découpez une grande chaîne en fragments de cinq caractères chacun. Rassemblez ces morceaux dans l'ordre inverse.
  3. Tâchez d'écrire un script qui fera exactement le contraire de ce que fait l'opérateur d'indexage ([]) : au lieu de partir d'un index donné pour retrouver le caractère correspondant, il devra retrouver l'index correspondant à un caractère donné, à partir du nom de la chaîne à traiter et du caractère à trouver. Exemple : pour "Juliette & Roméo", "&" il devra afficher : 9, ou -1 si le caractère est introuvable.
  4. Améliorez le script en lui ajoutant une troisième variable : l'index à partir duquel la recherche doit s'effectuer dans la chaîne. Ainsi par exemple, pour : "César & Cléopâtre", "r", 5, il devra afficher : 15 (et non 4 !)
  5. Écrivez un script qui compte le nombre d'occurrences d'un caractère donné dans une chaîne. Ainsi, pour "ananas au jus", "a" il devra afficher : 4.

Solution

  1. IndexError: list index out of range
  2. # Découpage d'une chaîne en fragments :
    chain ="abcdefghijklmnopqrstuvwxyz123456789"
    n = 5
    
    # Découpage de "chain" en une liste de fragments de n caractères"
    d, f = 0, n             # indices de début et de fin de fragment
    tt = []                 # liste à construire
    while d < len(chain):
    	if f > len(chain):  # on ne peut pas découper au-delà de la fin
    		f = len(chain)
    	fr = chain[d:f]     # découpage d'un fragment
    	tt.append(fr)       # ajout du fragment à la liste
    	d, f = f, f + n      # indices suivants 
    print(tt)
    
    # Rassemble les éléments de la liste tt dans l'ordre inverse"
    chain = ""              # chaîne à construire
    i = len(tt)             # on commence par la fin de la liste
    while i > 0 :
    	i = i - 1           # le dernier élément possède l'indice n - 1
    	chain = chain + tt[i]
    print(chain)
    
  3. # Rechercher l'indice d'un caractère dans une chaîne
    chain, car = "Coucou c'est moi", "z"
    start = 0
    
    # Trouve l'indice du caractère car dans "chain"
    i = start
    while i < len(chain):
    	if chain[i] == car:
    		print(i)	# le caractère est trouvé -> on termine
    	i = i + 1
    print(-1)       		# toute la chaîne a été scannée sans succès 
    
    # Autres tests :
    chain, car = "Juliette & Roméo", "&"
    chain, car, start = "César & Cléopâtre", "r", 5
    
  4. Réfléchissez !
  5. Réfléchissez !

Exercices

  1. 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...].
  2. É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
    
  3. É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.
    
  4. É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 contiendra [5, 3, 75, 15]. Astuce : pensez à utiliser l'opérateur modulo (%) déjà cité précédemment.
  5. Écrivez un programme qui analyse un par un tous les éléments d'une liste de mots (par exemple : ['Jean', 'Maximilien', 'Brigitte', 'Sonia', 'Jean-Pierre', 'Sandra'] pour générer deux nouvelles listes. L'une contiendra les mots comportant moins de 6 caractères, l'autre les mots comportant 6 caractères ou davantage.

Solution

  1. # Combinaison de deux listes en une seule
    
    # Listes fournies au départ :
    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']
    # Nouvelle liste à construire (vide au départ) :
    t3 = []
    # Boucle de traitement :
    i = 0
    while i < len(t1):
        t3.append(t2[i])
        t3.append(t1[i])
        i = i + 1
    
    # Affichage :
    print t3
    
  2. # Affichage des éléments d'une liste
    
    # Liste fournie au départ :
    t2 = ['Janvier','Février','Mars','Avril','Mai','Juin',
          'Juillet','Août','Septembre','Octobre','Novembre','Décembre']
    # Affichage :
    i = 0
    while i < len(t2):
        print t2[i],
        i = i + 1
    
  3. # Recherche du plus grand élément d'une liste
    
    # Liste fournie au départ :
    tt = [32, 5, 12, 8, 3, 75, 2, 15]
    # Au fur et à mesure du traitement de la liste, on mémorisera dans
    # la variable ci-dessous la valeur du plus grand élément déjà trouvé :
    max = 0
    # Examen de tous les éléments :
    i = 0
    while i < len(tt):
        if tt[i] > max:
            max = tt[i]         # mémorisation d'un nouveau maximum
        i = i + 1
    # Affichage :
    print "Le plus grand élément de cette liste a la valeur", max
    
  4. # Séparation des nombres pairs et impairs
    
    # Liste fournie au départ :
    tt = [32, 5, 12, 8, 3, 75, 2, 15]
    pairs = []
    impairs = []
    # Examen de tous les éléments :
    i = 0
    while i < len(tt):
        if tt[i] % 2 == 0:
            pairs.append(tt[i])
        else:
            impairs.append(tt[i])
        i = i + 1
    # Affichage :
    print "Nombres pairs :", pairs
    print "Nombres impairs :", impairs
    
  5. Réfléchissez !

Exercices

  1. Écrivez un script qui génère la liste des carrés et des cubes des nombres de 20 à 40.
  2. Écrivez un script qui crée automatiquement la liste des sinus des angles de 0° à 90° , par pas de 5°. Attention : la fonction sin() du module math considère que les angles sont fournis en radians (360° = 2 p radians)
  3. Écrivez un script qui permette d'obtenir à l'écran les 15 premiers termes des tables de multiplication par 2, 3, 5, 7, 11, 13, 17, 19 (ces nombres seront placés au départ dans une liste) sous la forme d'une table similaire à la suivante :
    2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
    3 6 9 12 15 18 21 24 27 30 33 36 39 42 45
    5 10 15 20 25 30 35 40 45 50 55 60 65 70 75
    etc.
  4. Soit la liste suivante :
    ['Jean-Michel', 'Marc', 'Vanessa', 'Anne', 'Maximilien', 'Alexandre-Benoît', 'Louise']
    Écrivez un script qui affiche chacun de ces noms avec le nombre de caractères correspondant.
  5. Vous disposez d'une liste de nombres entiers quelconques, certains d'entre eux étant présents en plusieurs exemplaires. Écrivez un script qui recopie cette liste dans une autre, en omettant les doublons. La liste finale devra être triée.
  6. Écrivez un script qui recherche le mot le plus long dans une phrase donnée (l'utilisateur du programme doit pouvoir entrer une phrase de son choix).
  7. Écrivez un script capable d'afficher la liste de tous les jours d'une année imaginaire, laquelle commencerait un Jeudi. Votre script utilisera lui-même trois listes : une liste des noms de jours de la semaine, une liste des noms des mois, et une liste des nombres de jours que comportent chacun des mois (ne pas tenir compte des années bissextiles).
    Exemple de sortie :
    Jeudi 1 Janvier Vendredi 2 Janvier Samedi 3 Janvier Dimanche 4 Janvier
    ... et ainsi de suite jusqu'au Jeudi 31 Décembre.
  8. Vous avez à votre disposition un fichier texte qui contient un certain nombre de noms d'élèves. Écrivez un script qui effectue une copie triée de ce fichier.
  9. Écrivez un script permettant de trier une liste. Il ne pourra pas utiliser la méthode intégrée "sort()" de Python : vous devez donc définir vous-même l'algorithme de tri.

Solution

  1. Réfléchissez !
  2. Réfléchissez !
  3. # Affichage de tables de multiplication
    m, n = 3, 15
    chain =""
    for i in range(n):
        v = m * (i+1)               # calcul d'un des termes
        chain = chain + "%4d" % (v) # formatage à 4 caractères
    print(chain)
    
    3   6   9  12  15  18  21  24  27  30  33  36  39  42  45
    
  4. # Simple parcours d'une liste :
    lst = ['Jean-Michel', 'Marc', 'Vanessa', 'Anne',
           'Maximilien', 'Alexandre-Benoît', 'Louise']
    
    for e in lst:
        print("%s : %s caractères" % (e, len(e)))
    
  5. # Élimination de doublons
    
    lst = [9, 12, 40, 5, 12, 3, 27, 5, 9, 3, 8, 22, 40, 3, 2, 4, 6, 25]
    lst2 = []
    
    for el in lst:
        if el not in lst2:
            lst2.append(el)
    
    lst2.sort()
    print(lst2)
    
  6. Réfléchissez !
  7. # Afficher tous les jours d'une année :
    ## Cette variante utilise une liste de listes ##
    ## (que l'on pourrait aisément remplacer par deux listes distinctes)
    
    # La liste ci-dessous contient deux éléments qui sont eux-mêmes des listes.
    # l'élément 0 contient les nombres de jours de chaque mois, tandis que
    # l'élément 1 contient les noms des douze mois :
    mois = [[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
            ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet',
             'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre']]
    
    jour = ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi']
    
    ja, jm, js, m = 0, 0, 0, 0
    
    while ja <365:
        ja, jm = ja +1, jm +1    # ja = jour dans l'année, jm = jour dans le mois
        js = (ja +3) % 7         # js = jour de la semaine. Le décalage ajouté 
                                 #      permet de choisir le jour de départ
      
        if jm > mois[0][m]:               # élément m de l'élément 0 de la liste
            jm, m = 1, m+1
    
        print jour[js], jm, mois[1][m]    # élément m de l'élément 1 de la liste
    
  8. Réfléchissez !
  9. Réfléchissez !


Tuples

Description d'un tuple[modifier | modifier le wikicode]

Vous devez vous rappeler une autre différence importante entre chaînes et listes : il n'est pas possible de changer les caractères au sein d'une chaîne existante, alors que vous pouvez modifier les éléments d'une liste. En d'autres termes, les listes sont des séquences modifiables, alors que les chaînes sont des séquences non-modifiables. Exemple :

>>> liste =['jambon','fromage','miel','confiture','chocolat']
>>> liste[1:3] =['salade']
>>> print liste
['jambon', 'salade', 'confiture', 'chocolat']
>>> chaine ='Roméo préfère Juliette'
>>> chaine[14:] ='Brigitte'
          ***** ==> Erreur: object doesn't support slice assignment  *****

Nous essayons de modifier la fin de la chaîne, mais cela ne marche pas. La seule possibilité d'arriver à nos fins est de créer une nouvelle chaîne et d'y recopier ce que nous voulons changer :

>>> chaine = chaine[:14] +'Brigitte'
>>> print chaine
Roméo préfère Brigitte

Python propose un type de données appelé tuple (anglicisme informatique signifiant "Table UPLEt"), qui est assez semblable à une liste mais qui n'est pas modifiable. Les tuples sont donc préférables aux listes partout où l'on veut être certain que les données transmises ne soient pas modifiées par erreur au sein d'un programme. En outre, les tuples sont moins « gourmands » en ressources système (ils occupent moins de place en mémoire).

Du point de vue de la syntaxe, un tuple est une collection d'éléments séparés par des virgules :

>>> tuple = 'a', 'b', 'c', 'd', 'e'
>>> print(tuple)
('a', 'b', 'c', 'd', 'e')

Pour améliorer la lisibilité du code, il est vivement conseillé de déclarer le tuple en évidence en l'enfermant dans une paire de parenthèses, comme l'instruction "print" de Python le fait elle-même.

>>> tuple = ('a', 'b', 'c', 'd', 'e')

Les opérations que l'on peut effectuer sur des tuples sont syntaxiquement similaires à celles que l'on effectue sur les listes, si ce n'est que les tuples ne sont pas modifiables :

>>> print(tuple[2:4])
('c', 'd')

>>> tuple[1:3] = ('x', 'y')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

>>> tuple = ('André',) + tuple[1:]	
>>> print(tuple)
('André', 'b', 'c', 'd', 'e')

Remarquez qu'il faut toujours au moins une virgule pour définir un tuple (le dernier exemple ci-dessus utilise un tuple contenant un seul élément : 'André').


Dictionnaires

Déclarations[modifier | modifier le wikicode]

Le dictionnaire ou tableau associatif n'est pas une séquence mais un autre type composite. Ils ressemblent aux listes dans une certaine mesure (ils sont modifiables comme elles), mais les éléments que nous allons y enregistrer ne seront pas disposés dans un ordre immuable. En revanche, nous pourrons accéder à n'importe lequel d'entre eux à l'aide d'un index spécifique que l'on appellera une clé, laquelle pourra être alphabétique, numérique, ou même d'un type composite sous certaines conditions.

 comme dans une liste, les éléments mémorisés dans un dictionnaire peuvent être de n'importe quel type (valeurs numériques, chaînes, listes, etc.).

Création d'un dictionnaire[modifier | modifier le wikicode]

A titre d'exemple, nous allons créer un dictionnaire de langue, pour la traduction de termes informatiques anglais en français. Dans ce dictionnaire, les index seront des chaînes de caractères.

Puisque le type dictionnaire est un type modifiable, nous pouvons commencer par créer un dictionnaire vide, puis le remplir petit à petit. Du point de vue syntaxique, on reconnaît une structure de données de type dictionnaire au fait que ses éléments sont enfermés dans une paire d'accolades. Un dictionnaire vide sera donc noté { } :

dico = {}
dico['computer'] = 'ordinateur'
dico['mouse'] ='souris'
dico['keyboard'] ='clavier'
print dico
{'computer': 'ordinateur', 'keyboard': 'clavier', 'mouse': 'souris'}

Comme vous pouvez l'observer dans la ligne ci-dessus, un dictionnaire apparaît comme une série d'éléments séparés par des virgules (le tout étant enfermé entre deux accolades}. Chacun de ces éléments est constitué d'une paire d'objets : un index et une valeur, séparés par un double point.

Dans un dictionnaire, les index s'appellent des clés, et les éléments peuvent donc s'appeler des paires clé-valeur. Vous pouvez constater que l'ordre dans lequel les éléments apparaissent à la dernière ligne ne correspond pas à celui dans lequel nous les avons fournis. Cela n'a strictement aucune importance : nous n'essaierons jamais d'extraire une valeur d'un dictionnaire à l'aide d'un index numérique. Au lieu de cela, nous utiliserons les clés :

>>> print dico['mouse']
souris

Contrairement à ce qui se passe avec les listes, il n'est pas nécessaire de faire appel à une méthode particulière pour ajouter de nouveaux éléments à un dictionnaire : il suffit de créer une nouvelle paire clé-valeur.

Opérations sur les dictionnaires[modifier | modifier le wikicode]

Pour en enlever, vous utiliserez l'instruction del. Créons pour l'exemple un autre dictionnaire, destiné cette fois à contenir l'inventaire d'un stock de fruits. Les index (ou clés) seront les noms des fruits, et les valeurs seront les masses de ces fruits répertoriées dans le stock (il s'agit donc cette fois de valeurs de type numérique).

>>> invent = {'pommes': 430, 'bananes': 312, 'oranges' : 274, 'poires' : 137}
>>> print invent
{'oranges': 274, 'pommes': 430, 'bananes': 312, 'poires': 137}

Si le patron décide de liquider toutes les pommes et de ne plus en vendre, nous pouvons enlever cette entrée dans le dictionnaire :

>>> del invent['pommes']
>>> print invent
{'oranges': 274, 'bananes': 312, 'poires': 137}

La fonction len() est utilisable avec un dictionnaire : elle en renvoie le nombre d'éléments.

Les dictionnaires sont des objets[modifier | modifier le wikicode]

On peut appliquer aux dictionnaires un certain nombre de méthodes spécifiques :

keys et values[modifier | modifier le wikicode]

La méthode keys() renvoie la liste des clés utilisées dans le dictionnaire :

>>> print dico.keys()
['computer', 'keyboard', 'mouse']

La méthode values() renvoie la liste des valeurs mémorisées dans le dictionnaire :

>>> print invent.values()
[274, 312, 137]

has_key[modifier | modifier le wikicode]

La méthode has_key() permet de savoir si un dictionnaire comprend une clé déterminée. On fournit la clé en argument, et la méthode renvoie une valeur 'vraie' ou 'fausse' (en fait, 1 ou 0), suivant que la clé est présente ou pas :

>>> print invent.has_key('bananes')
1
>>> if invent.has_key('pommes'):
       print 'nous avons des pommes'
else:
       print 'pas de pommes, sorry'

pas de pommes, sorry

items[modifier | modifier le wikicode]

La méthode items() extrait du dictionnaire une liste équivalente de tuples :

>>> print invent.items()
[('oranges', 274), ('bananes', 312), ('poires', 137)]

Il est donc utilisé pour les "foreach" :

for key, value in invent.items():
    print "Clé : %s, valeur : %s." % (key, value)

copy[modifier | modifier le wikicode]

La méthode copy() permet d'effectuer une vraie copie d'un dictionnaire. Il faut savoir en effet que la simple affectation d'un dictionnaire existant à une nouvelle variable crée seulement une nouvelle référence vers le même objet, et non un nouvel objet (aliasing). Par exemple, l'instruction ci-dessous ne définit pas un nouveau dictionnaire (contrairement aux apparences) :

>>> stock = invent
>>> print stock
{'oranges': 274, 'bananes': 312, 'poires': 137}

>>> del invent['bananes']
>>> print stock
{'oranges': 274, 'poires': 137}

Si nous modifions "invent", alors stock aussi est modifié, et vice-versa (ces deux noms désignent en effet le même objet dictionnaire dans la mémoire de l'ordinateur).

Pour obtenir une vraie copie (indépendante) d'un dictionnaire préexistant, il faut employer la méthode copy() :

>>> magasin = stock.copy()
>>> magasin['prunes'] = 561
>>> print magasin
{'oranges': 274, 'prunes': 561, 'poires': 137}
>>> print stock
{'oranges': 274, 'poires': 137}
>>> print invent
{'oranges': 274, 'poires': 137}

update[modifier | modifier le wikicode]

Il est possible de concaténer deux dictionnaires avec cette méthode :

>>> d = {'apples': 1, 'oranges': 3, 'pears': 2}
>>> ud = {'pears': 4, 'grapes': 5, 'lemons': 6}
>>> d.update(ud)
>>> d
{'grapes': 5, 'pears': 4, 'lemons': 6, 'apples': 1, 'oranges': 3}
>>>
 les doublons sont automatiquement fusionnés.

Parcours d'un dictionnaire[modifier | modifier le wikicode]

Vous pouvez utiliser une boucle for pour traiter successivement tous les éléments contenus dans un dictionnaire, mais attention :

  • Au cours de l'itération, ce sont les clés utilisées dans le dictionnaire qui seront successivement affectées à la variable de travail, et non les valeurs.
  • L'ordre dans lequel les éléments seront extraits est imprévisible (puisqu'un dictionnaire n'est pas une séquence).

Exemple :

>>> invent ={"oranges":274, "poires":137, "bananes":312}
>>> for clef in invent:
...    print clef
    
poires
bananes
oranges

Si vous souhaitez effectuer un traitement sur les valeurs, il vous suffit alors de récupérer chacune d'elles à partir de la clé correspondante :

for clef in invent:
    print clef, invent[clef]
    
poires 137
bananes 312
oranges 274

Cette manière de procéder n'est cependant pas idéale, ni en termes de performances ni même du point de vue de la lisibilité. Il est recommandé de plutôt faire appel à la méthode items() décrite à la section précédente :

for clef, valeur in invent.items():
    print clef, valeur
    
poires 137
bananes 312
oranges 274

Les clés ne sont pas nécessairement des chaînes de caractères[modifier | modifier le wikicode]

Jusqu'à présent nous avons décrit des dictionnaires dont les clés étaient à chaque fois des valeurs de type string. En fait nous pouvons utiliser en guise de clés n'importe quel type de donnée non modifiable : des entiers, des réels, des chaînes de caractères, et même des tuples.

Considérons par exemple que nous voulions répertorier les arbres remarquables situés dans un grand terrain rectangulaire. Nous pouvons pour cela utiliser un dictionnaire, dont les clés seront des tuples indiquant les coordonnées x,y de chaque arbre :

>>> arb = {}
>>> arb[(1,2)] = 'Peuplier'
>>> arb[(3,4)] = 'Platane'
>>> arb[6,5] = 'Palmier'
>>> arb[5,1] = 'Cycas'
>>> arb[7,3] = 'Sapin'

>>> print arb
{(3, 4): 'Platane', (6, 5): 'Palmier', (5, 1): 'Cycas', (1, 2): 'Peuplier', (7, 3): 'Sapin'}
>>> print arb[(6,5)]
palmier
foret disposée en grille dont les arbres sont générés par un dictionnaire

Vous pouvez remarquer que nous avons allégé l'écriture à partir de la troisième ligne, en profitant du fait que les parenthèses délimitant les tuples sont facultatives (à utiliser avec prudence !).

Dans ce genre de construction, il faut garder à l'esprit que le dictionnaire contient des éléments seulement pour certains couples de coordonnées. Ailleurs, il n'y a rien. Par conséquent, si nous voulons interroger le dictionnaire pour savoir ce qui se trouve là où il n'y a rien, comme par exemple aux coordonnées (2,1), nous allons provoquer une erreur :

>>> print arb[1,2]
Peuplier
>>> print arb[2,1]
                ***** Erreur : KeyError: (2, 1)  *****

Pour résoudre ce petit problème, nous pouvons utiliser la méthode get() :

>>> print arb.get((1,2),'néant')
Peuplier
>>> print arb.get((2,1),'néant')
néant

Le premier argument transmis à cette méthode est la clé de recherche, le second argument est la valeur que nous voulons obtenir en retour si la clé n'existe pas dans le dictionnaire.

Les dictionnaires ne sont pas des séquences[modifier | modifier le wikicode]

Comme vous l'avez vu plus haut, les éléments d'un dictionnaire ne sont pas disposés dans un ordre particulier. Des opérations comme la concaténation et l'extraction (d'un groupe d'éléments contigus) ne peuvent donc tout simplement pas s'appliquer ici. Si vous essayez tout de même, Python lèvera une erreur lors de l'exécution du code :

>>> print arb[1:3]
                ***** Erreur : KeyError: slice(1, 3, None) *****

Vous avez vu également qu'il suffit d'affecter un nouvel indice (une nouvelle clé) pour ajouter une entrée au dictionnaire. Cela ne marcherait pas avec les listes :

>>> invent['cerises'] = 987
>>> print invent
{'oranges': 274, 'cerises': 987, 'poires': 137}

>>> liste =['jambon', 'salade', 'confiture', 'chocolat']
>>> liste[4] ='salami'
          ***** IndexError: list assignment index out of range  *****

Du fait qu'ils ne sont pas des séquences, les dictionnaires se révèlent donc particulièrement précieux pour gérer des ensembles de données où l'on est amené à effectuer fréquemment des ajouts ou des suppressions, dans n'importe quel ordre. Ils remplacent avantageusement les listes lorsqu'il s'agit de traiter des ensembles de données numérotées, dont les numéros ne se suivent pas.

Exemple :

>>> client = {}
>>> client[4317] = "Dupond"
>>> client[256] = "Durand"
>>> client[782] = "Schmidt"

etc.

Exercices

  1. Écrivez un script qui crée un mini-système de base de données fonctionnant à l'aide d'un dictionnaire, et dans lequel vous mémoriserez les noms d'une série de copains, leur âge et leur taille. Votre script devra comporter deux fonctions : la première pour le remplissage du dictionnaire, et la seconde pour sa consultation. Dans la fonction de remplissage, utilisez une boucle pour accepter les données entrées par l'utilisateur. Dans le dictionnaire, le nom de l'élève servira de clé d'accès, et les valeurs seront constituées de tuples (âge, taille), dans lesquels l'âge sera exprimé en années (donnée de type entier), et la taille en mètres (donnée de type réel). La fonction de consultation comportera elle aussi une boucle, dans laquelle l'utilisateur pourra fournir un nom quelconque pour obtenir en retour le couple « âge, taille » correspondant. Le résultat de la requête devra être une ligne de texte bien formatée, telle par exemple : « Nom : Jean Dhoute - âge : 15 ans - taille : 1.74 m ».
  2. Écrivez une fonction qui échange les clés et les valeurs d'un dictionnaire (ce qui permettra par exemple de transformer un dictionnaire anglais/français en un dictionnaire français/anglais). (On suppose que le dictionnaire ne contient pas plusieurs valeurs identiques).

Solution

  1. #!/usr/bin/env python
    # coding: utf-8
    
    # Création du dictionnaire
    dico ={}
    while 1:
        choix = raw_input("Choisissez : (R)emplir - (C)onsulter - (T)erminer : ")
        if choix.upper() == 'T':
            break
    
        elif choix.upper() == 'R':
    	nom = raw_input("Entrez le nom (ou <enter> pour terminer) : ")
    	if nom == "":
    		break
    	age = int(raw_input("Entrez l'âge (nombre entier !) : "))
    	taille = float(raw_input("Entrez la taille (en mètres) : "))
    	dico[nom] = (age, taille)
    
        elif choix.upper() == 'C':
    	# Consultation
    	nom = raw_input("Entrez le nom (ou <enter> pour terminer) : ")
    	if nom == "":
    		break
    	if dico.has_key(nom):           # le nom est-il répertorié ?
    		item = dico[nom]            # consultation proprement dite
    		age, taille = item[0], item[1]
    		print "Nom : %s - âge : %s ans - taille : %s m."\
    			   % (nom, age, taille)          
    	else:
    		print "*** nom inconnu ! ***"
    
  2. # Échange des clés et des valeurs dans un dictionnaire
    dico = {'Computer':'Ordinateur',
            'Mouse':'Souris',
            'Keyboard':'Clavier',
            'Hard disk':'Disque dur',
            'Screen':'Ecran'}
    
    print(dico)
    
    dic_inv ={} 
    for cle in dico:
    	item = dico[cle]  
    	dic_inv[item] = cle
    
    print(dic_inv)
    

Construction d'un histogramme à l'aide d'un dictionnaire[modifier | modifier le wikicode]

Les dictionnaires constituent un outil très élégant pour construire des histogrammes.

Supposons par exemple que nous voulions établir l'histogramme qui représente la fréquence d'utilisation de chacune des lettres de l'alphabet dans un texte donné. L'algorithme permettant de réaliser ce travail est extraordinairement simple si on le construit sur base d'un dictionnaire :

>>> texte ="les saucisses et saucissons secs sont dans le saloir"
>>> lettres ={}
>>> for c in texte:
        lettres[c] = lettres.get(c, 0) + 1
	
>>> print lettres
{'t': 2, 'u': 2, 'r': 1, 's': 14, 'n': 3, 'o': 3, 'l': 3, 'i': 3, 'd': 1, 
'e': 5, 'c': 3, ' ': 8, 'a': 4}

Nous commençons par créer un dictionnaire vide : lettres. Ensuite, nous allons remplir ce dictionnaire en utilisant les caractères de l'alphabet en guise de clés. Les valeurs que nous mémoriserons pour chacune de ces clés seront les fréquences des caractères correspondants dans le texte. Afin de calculer celles-ci, nous effectuons un parcours de la chaîne de caractères texte. Pour chacun de ces caractères, nous interrogeons le dictionnaire à l'aide de la méthode get(), en utilisant le caractère en guise de clé, afin d'y lire la fréquence déjà mémorisée pour ce caractère. Si cette valeur n'existe pas encore, la méthode get() doit renvoyer une valeur nulle. Dans tous les cas, nous incrémentons la valeur trouvée, et nous la mémorisons dans le dictionnaire à l'emplacement qui correspond à la clé (c'est-à-dire au caractère en cours de traitement).

Pour fignoler notre travail, nous pouvons encore souhaiter afficher l'histogramme dans l'ordre alphabétique. Pour ce faire, nous pensons immédiatement à la méthode sort(), mais celle-ci ne peut s'appliquer qu'aux listes. Qu'à cela ne tienne ! Nous avons vu plus haut comment nous pouvions convertir un dictionnaire en une liste de tuples :

>>> lettres_triees = lettres.items()
>>> lettres_triees.sort()
>>> print lettres_triees
[(' ', 8), ('a', 4), ('c', 3), ('d', 1), ('e', 5), ('i', 3), ('l', 3), 
('n', 3), ('o', 3), ('r', 1), ('s', 14), ('t', 2), ('u', 2)]

Exercices

  1. Vous avez à votre disposition un fichier texte quelconque (pas trop gros). Écrivez un script qui compte les occurrences de chacune des lettres de l'alphabet dans ce texte (on ne tiendra pas compte du problème des lettres accentuées)..
  2. Modifiez le script ci-dessus afin qu'il établisse une table des occurrences de chaque mot dans le texte. Conseil : dans un texte quelconque, les mots ne sont pas seulement séparés par des espaces, mais également par divers signes de ponctuation. Pour simplifier le problème, vous pouvez commencer par remplacer tous les caractères non-alphabétiques par des espaces, et convertir la chaîne résultante en une liste de mots à l'aide de la méthode split().
  3. Vous avez à votre disposition un fichier texte quelconque (pas trop gros). Écrivez un script qui analyse ce texte, et mémorise dans un dictionnaire l'emplacement exact de chacun des mots (compté en nombre de caractères à partir du début). Lorsqu'un même mot apparaît plusieurs fois, tous ses emplacements doivent être mémorisés : chaque valeur de votre dictionnaire doit donc être une liste d'emplacements.

Solution

  1. # histogramme
    nFich = raw_input('Nom du fichier : ')
    fi = open(nFich, 'r')
    texte = fi.read()		# conversion du fichier en une chaîne de caractères
    fi.close()
    
    print texte
    dico ={}
    for c in texte:
        c = c.upper()		# conversion de toutes les lettres en majuscules
        dico[c] = dico.get(c, 0) +1
    
    liste = dico.items()
    liste.sort()
    print liste
    
  2. nFich = raw_input('Nom du fichier à traiter : ')
    fi = open(nFich, 'r')
    texte = fi.read()
    fi.close()
    
    # afin de pouvoir aisément séparer les mots du texte, on commence 
    # par convertir tous les caractères non-alphabétiques en espaces  :
    
    alpha = "abcdefghijklmnopqrstuvwxyzéèàùçâêîôûäëïöü"
    
    lettres = ''            # nouvelle chaîne à construire
    for c in texte:
        c = c.lower()       # conversion de chaque caractère en minuscule
        if c in alpha:
            lettres = lettres + c
        else:
            lettres = lettres + ' '
    
    # conversion de la chaîne résultante en une liste de mots :
    mots = lettres.split()
    
    
    # construction de l'histogramme :
    dico ={}
    for m in mots:
        dico[m] = dico.get(m, 0) +1
    
    liste = dico.items()
    
    # tri de la liste résultante :
    liste.sort()
    
    # affichage en clair :
    for item in liste:
        print item[0], ":", item[1]
    
  3. # encodage d'un texte dans un dictionnaire
    
    nFich = raw_input('Nom du fichier à traiter : ')
    fi = open(nFich, 'r')
    texte = fi.read()
    fi.close()
    
    # On considère que les mots sont des suites de caractères faisant partie
    # de la chaîne ci-dessous. Tous les autres sont des séparateurs :
    
    alpha = "abcdefghijklmnopqrstuvwxyzéèàùçâêîôûäëïöü"
    
    # construction du dictionnaire :
    dico ={}
    # parcours de tous les caractères du texte :
    i =0                    # indice du caractère en cours de lecture
    mot =""                 # variable de travail : mot en cours de lecture
    for c in texte:
        c = c.lower()       # conversion de chaque caractère en minuscule
        
        if c in alpha:      # car. alphab. => on est à l'intérieur d'un mot
            mot = mot + c   
        else:               # car. non-alphabétique => fin de mot
            if mot != "":   # afin d'ignorer les car. non-alphabétiques successifs
                # pour chaque mot, on construit une liste d'indices :
                if dico.has_key(mot):       # mot déjà répertorié :
                    dico[mot].append(i)     # ajout d'un indice à la liste
                else:                       # mot rencontré pour la 1e fois :
                    dico[mot] =[i]          # création de la liste d'indices
                mot =""     # préparer la lecture du mot suivant
        i = i+1             # indice du caractère suivant
          
    # Affichage du dictionnaire, en clair :
    for clef, valeur in dico.items():
        print clef, ":", valeur
    

Contrôle du flux d'exécution à l'aide d'un dictionnaire[modifier | modifier le wikicode]

Il arrive fréquemment que l'on ait à diriger l'exécution d'un programme dans différentes directions, en fonction de la valeur prise par une variable. Vous pouvez bien évidemment traiter ce problème à l'aide d'une série d'instructions if - elif - else , mais cela peut devenir assez lourd et inélégant si vous avez affaire à un grand nombre de possibilités. Exemple :

materiau = raw_input("Choisissez le matériau : ")

if materiau == 'fer':
    fonctionA()
elif materiau == 'bois':
    fonctionC()
elif materiau == 'cuivre':
    fonctionB()
elif materiau == 'pierre':
    fonctionD()
elif   ... etc ...

Les langages de programmation proposent souvent des instructions spécifiques pour traiter ce genre de problème, telles les instructions switch ou case du C ou du Pascal. Python n'en propose aucune, mais vous pouvez vous tirer d'affaire dans bien des cas à l'aide d'une liste, ou mieux encore à l'aide d'un dictionnaire. Exemple :

materiau = raw_input("Choisissez le matériau : ")

dico = {'fer':fonctionA,
        'bois:fonctionC,
        'cuivre':fonctionB,
        'pierre':fonctionD,
	    ... etc ...}
dico[materiau]()

Les deux instructions ci-dessus pourraient être condensées en une seule, mais nous les laissons séparées pour bien détailler le mécanisme :

  • La première instruction définit un dictionnaire dico dans lequel les clés sont les différentes possibilités pour la variable materiau, et les valeurs, les noms des fonctions à invoquer en correspondance. Notez bien qu'il s'agit seulement des noms de ces fonctions, qu'il ne faut surtout pas faire suivre de parenthèses dans ce cas (Sinon Python exécuterait chacune de ces fonctions au moment de la création du dictionnaire).
  • La seconde instruction invoque la fonction correspondant au choix opéré à l'aide de la variable materiau. Le nom de la fonction est extrait du dictionnaire à l'aide de la clé, puis associé à une paire de parenthèses. Python reconnaît alors un appel de fonction tout à fait classique et l'exécute.

Vous pouvez encore améliorer la technique ci-dessus en remplaçant cette instruction par sa variante ci-dessous, qui fait appel à la méthode get() afin de prévoir le cas où la clé demandée n'existerait pas dans le dictionnaire (vous obtenez de cette façon l'équivalent d'une instruction else terminant une longue série de elif) :

dico.get(materiau, fonctAutre)()

Lorsque la la valeur de la variable "materiau "ne correspond à aucune clé du dictionnaire, c'est la fonction fonctAutre() qui est invoquée.


Dates

Module datetime[modifier | modifier le wikicode]

Les dates se manipulent à l'aide du module datetime[1].

Syntaxe[modifier | modifier le wikicode]

>>> import datetime
>>> maDate = datetime.datetime.now()
>>> print (maDate)
2017-04-22 01:49:41.230711
>>>

Impossible de tronquer une date complète comme une chaine de caractères, il faut utiliser les fonctions du module :

>>> print (maDate.year)
2017
>>> print (maDate.month)
4
>>> print (maDate.day)
22
>>> print (maDate.hour)
1
>>> print (maDate.minute)
49
>>> print (maDate.second)
41
>>> print (maDate.microsecond)
230711
>>>

Les variables de ce type sont très faciles à additionner et soustraire :

>>> maDateDeFin = datetime.datetime.now()
>>> print (maDateDeFin - maDate)
0:04:38.266647

Références[modifier | modifier le wikicode]


Ensembles

Définition[modifier | modifier le wikicode]

En Python, les ensembles sont définis par le mot "set()"[1] depuis Python 2.3, d'abord en important le module du même nom, puis depuis nativement Python 2.6, avec "frozenset()".

Un ensemble est une collection non ordonnée d'objets, contrairement aux séquences comme les listes et les tuples dans lesquels chaque élément est indexé. Un ensemble ne peut pas contenir de doublon : on ne peut y trouver des éléments que zéro ou une fois. Tous les membres d'un ensemble doivent être hachable, comme les clés des dictionnaires. A titre d'exemple, les scalaires comme les entiers, flottants, tuples, et chaines sont hachables ; par contre les dictionnaires, listes, et ensembles ne le sont pas.

Exemple :

set1 = set()                    # Nouvel ensemble vide
set1.add("cat")                 # Ajout d'un membre
set1.update(["dog", "mouse"])   # Ajout de plusieurs membres
if "cat" in set1:               # Recherche d'un membre
  set1.remove("cat")            # Retrait d'un membre
#set1.remove("elephant")        - Erreur de retrait d'un membre introuvable
set1.discard("elephant")        # Aucune erreur de retrait d'un membre introuvable

print(set1)                     # Affichage d'un ensemble
for item in set1:               # Itération pour chaque élément
  print(item)
print("Item count:", len(set1)) # Compte des éléments

#1stitem = set1[0]              # Erreur d'index introuvable
isempty = len(set1) == 0        # Test si l'ensemble est vide
set1 = set(["cat", "dog"])      # Initialisation de l'ensemble depuis une liste de membre
set2 = set(["dog", "mouse"])
set3 = set1 & set2              # Intersection
set4 = set1 | set2              # Union
set5 = set1 - set3              # Différence
set6 = set1 ^ set2              # Différence symétrique
issubset = set1 <= set2         # Test de sous-ensemble
issuperset = set1 >= set2       # Test de sur-ensemble
set7 = set1.copy()              # Copie d'un ensemble
set7.remove("cat")
set8 = set1.copy()
set8.clear()                    # Effacement d'un ensemble
print(set1, set2, set3, set4, set5, set6, set7, set8, issubset, issuperset)

Construction d'ensembles[modifier | modifier le wikicode]

Une première méthode consiste à fournir un objet séquentiel en paramètre :

>>> set([0, 1, 2, 3])
set([0, 1, 2, 3])

>>> set("obtuse")
set(['b', 'e', 'o', 's', 'u', 't'])

Ajout de chaque membre un par un :

>>> s = set([12, 26, 54])
>>> s.add(32)
>>> s
set([32, 26, 12, 54])

Ajout de groupes de membres :

>>> s.update([26, 12, 9, 14])
>>> s
set([32, 9, 12, 14, 54, 26])
 si on ajoute un doublon avec "add()" ou "update()", cela n'a aucun effet.

Ajout par copie d'un autre ensemble :

>>> s2 = s.copy()
>>> s2
set([32, 9, 12, 14, 54, 26])

Recherche de membre[modifier | modifier le wikicode]

Pour chercher si un élément existe dans un ensemble, on utilise "in" :

>>> 32 in s
True
>>> 6 in s
False
>>> 6 not in s
True

Si un sous-ensemble existe dans un ensemble, c'est "issubset()" :

>>> s.issubset(set([32, 8, 9, 12, 14, -4, 54, 26, 19]))
True

Si un sur-ensemble contient un ensemble, c'est "issuperset()" :

>>> s.issuperset(set([9, 12]))
True

# Équivalent à :
>>> s.issuperset([9, 12])

# Équivalent à :
>>> s >= [9, 12]

Retrait de membre[modifier | modifier le wikicode]

Il existe quatre fonctions pour retirer des membres à un ensemble :

  1. "pop" : retire un membre non précisé.
  2. "remove" : retire le membre existant précisé.
  3. "discard" : retire un membre précisé.
  4. "clear" : retire tous les éléments.
>>> s = set([1,2,3,4,5,6])
>>> s.pop()
1
>>> s
set([2,3,4,5,6])

>>> s.remove(3)
>>> s
set([2,4,5,6])

>>> s.remove(9)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
KeyError: 9

>>> s.clear()
>>> s
set([])

Itération des ensembles[modifier | modifier le wikicode]

Les éléments n'étant pas ordonnés, il n'y a qu'une boucle possible :

>>> s = set("blerg")
>>> for n in s:
...     print n,
...
r b e l g

Opérations sur les ensembles[modifier | modifier le wikicode]

Python offre les mêmes opérations sur les ensembles qu'en mathématiques, applicables par soit par des opérateurs, soit par des fonctions équivalentes.

Intersection[modifier | modifier le wikicode]

Les éléments communs à deux ensembles.

>>> s1 = set([4, 6, 9])
>>> s2 = set([1, 6, 8])
>>> s1.intersection(s2)
set([6])
>>> s1 & s2
set([6])

>>> s1.intersection_update(s2)
>>> s1
set([6])

Union[modifier | modifier le wikicode]

Somme des éléments de deux ensembles.

>>> s1 = set([4, 6, 9])
>>> s2 = set([1, 6, 8])
>>> s1.union(s2)
set([1, 4, 6, 8, 9])
>>> s1 | s2
set([1, 4, 6, 8, 9])

Différence symétrique[modifier | modifier le wikicode]

La différence symétrique des deux cercles apparait en rouge.

Éléments contenu dans un seul ensemble à la fois, parmi deux.

>>> s1 = set([4, 6, 9])
>>> s2 = set([1, 6, 8])
>>> s1.symmetric_difference(s2)
set([8, 1, 4, 9])
>>> s1 ^ s2
set([8, 1, 4, 9])

>>> s1.symmetric_difference_update(s2)
>>> s1
set([8, 1, 4, 9])

Différence[modifier | modifier le wikicode]

Éléments non contenu dans un des deux ensembles.

>>> s1 = set([4, 6, 9])
>>> s2 = set([1, 6, 8])
>>> s1.difference(s2)
set([9, 4])
>>> s1 - s2
set([9, 4])

>>> s1.difference_update(s2)
>>> s1
set([9, 4])

Opérations non binaires[modifier | modifier le wikicode]

Depuis Python 2.6, les fonctions vues précédemment acceptent plus de deux arguments :

  1. .intersection()
  2. .union()
  3. .symetic_difference()
  4. .difference().

Exemple :

>>> s1 = set([3, 6, 7, 9])
>>> s2 = set([6, 7, 9, 10])
>>> s3 = set([7, 9, 10, 11])
>>> set.intersection(s1, s2, s3)
set([9, 7])

frozenset[modifier | modifier le wikicode]

Un "frozenset" (ensemble figé) se comporte comme un ensemble, sauf qu'il est immutable, c'est-à-dire qu'une fois créé, on ne peut pas le mettre à jour. Il dispose donc des mêmes fonctions que le type "set", mais sans "add", "update", "pop", "remove", "discard" et "clear".

De plus, ils sont hachables, ce qui leur permet de faire partie d'ensembles.

>>> fs = frozenset([2, 3, 4])
>>> s1 = set([fs, 4, 5, 6])
>>> s1
set([4, frozenset([2, 3, 4]), 6, 5])
>>> fs.intersection(s1)
frozenset([4])

>>> fs.add(6)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'frozenset' object has no attribute 'add'

Exercices[modifier | modifier le wikicode]

  1. Créer un set {'cat', 1, 2, 3}, appelé "s".
  2. Créer un set {'c', 'a', 't', '1', '2', '3'}.
  3. Créer un frozen set {'cat', 1, 2, 3}, appelé "fs".
  4. Créer un set contenant {frozenset({'cat', 2, 3, 1})}.

Références[modifier | modifier le wikicode]


Fonctions

Définir une fonction[modifier | modifier le wikicode]

Début d’un principe
Fin du principe


Une fonction Python est définie par le spécificateur "def" suivi du nom de la fonction et de ses paramètres :

def nomDeLaFonction(liste de paramètres):
    ... 
    bloc d'instructions
    ...
    return resultat
  • Vous pouvez choisir n'importe quel nom pour la fonction que vous créez, à l'exception des mots réservés du langage, et à la condition de n'utiliser aucun caractère spécial ou accentué (le caractère souligné « _ » est permis). Comme c'est le cas pour les noms de variables, il vous est conseillé d'utiliser surtout des lettres minuscules, notamment au début du nom.
  • Comme les instructions if et while, l'instruction def est une instruction composée. La ligne contenant cette instruction se termine obligatoirement par un double point, lequel introduit un bloc d'instructions que vous ne devez pas oublier d'indenter.
  • La liste de paramètres spécifie quelles informations il faudra fournir en guise d'arguments (avec leurs éventuelles valeurs par défaut) lorsque l'on voudra utiliser cette fonction (les parenthèses peuvent parfaitement rester vides si la fonction ne nécessite pas d'arguments).
  • Une fonction s'utilise pratiquement comme une instruction quelconque. Dans le corps d'un programme, un appel de fonction est constitué du nom de la fonction suivi de parenthèses.
  • Une fonction Python ne renvoie pas obligatoirement de résultat : le mot "return" est facultatif. S'il est absent, en termes de programmation on parlera alors plutôt de procédure que de fonction, et elle renverra "None".
  • Le type d'un paramètre sera le même que celui de l'argument qui aura été transmis à la fonction. Exemple :
>>> def afficher3fois(arg):
...     print arg, arg, arg

>>> afficher3fois(5)
5 5 5

>>> afficher3fois('zut')
zut zut zut

>>> afficher3fois([5, 7])
[5, 7] [5, 7] [5, 7]

>>> afficher3fois(6**2)
36 36 36

Fonctionnement[modifier | modifier le wikicode]

def factorielle(n):
    f = 1
    i = 1
    while i <= n:
         f = f * i
         i = i + 1
    return f # la valeur retournée

factorielle(7) # 5040

Récursivité[modifier | modifier le wikicode]

Une première fonction peut appeler une deuxième fonction, qui elle-même en appelle une troisième, etc. Mais elle peut aussi s'appeler elle-même :

def factorielle(n):
    if n == 0:
        return 1
    else:
        return n * factorielle(n-1)

factorielle(7) # 5040

Passage d'argument[modifier | modifier le wikicode]

Un fonction accepte entre zéro et 255 d'arguments :

>>> def addition(x, y):
        return x + y

addition(3, 4) # 7

>>> def multiplication(x, y):
        return x * y

multiplication(3, 4) # 12

La signature est ici "x" et "y" en paramètre.

Ces arguments peuvent être des variables, mais aussi des fonctions, appelées alors "fonctions de rappel" ou "callbacks". Exemple :

>>> def operation(x, y, f):
        return f(x, y)

operation(3, 4, addition)         # 7
operation(3, 4, multiplication)   # 12

Arguments facultatifs[modifier | modifier le wikicode]

Il suffit de définir une valeur par défaut à un argument pour le rendre facultatif. Naturellement, cette valeur est écrasée si l'argument est précisé :

>>> def f(x = None):
        if x:
            print(x)
print f() # None
print f(1) # 1 None

Arguments nommés[modifier | modifier le wikicode]

Pour ne pas être obligé de remplir tous les paramètres facultatifs dans l'ordre, il est possible de n'en n'appeler que quelques-uns s'ils sont nommés :

>>> def f(p1 = 0, p2 = 0, p3):
        ...
f(p3 = 1) # 1

Fonction lambda[modifier | modifier le wikicode]

Une fonction lambda est une fonction anonyme : elle n'est pas définie par def.

>>> def f(x):
       return x*2

>>> f(3)
6

>>> g = lambda x: x*2  # 1
>>> g(3)
6

>>> (lambda x: x*2)(3) # 2
6

1 et 2 sont des fonctions lambda.

Récupérer les arguments de la ligne de commande[modifier | modifier le wikicode]

La variable sys.argv contient les arguments de la ligne de commande, sous forme d'une liste dont le premier élément est le nom du script invoqué. Exemple :

Si le script truc.py contient

 #!/usr/bin/python
 #-*- coding: utf-8 -*-
 import sys
 print("Arguments : ", sys.argv)

alors l'invocation :

$ python truc.py -a rien -n=nervures

produira la sortie :

Arguments :  ['truc.py', '-a', 'rien', '-n=nervures']

Si on veut récupérer l'argument n° 2 :

 #!/usr/bin/python
 #-*- coding: utf-8 -*-
 import sys
 print("Argument 2 : ", sys.argv[2])

produira la sortie :

Argument 2 : 'rien'

Variables locales, variables globales[modifier | modifier le wikicode]

Lorsque nous définissons des variables à l'intérieur du corps d'une fonction, ces variables ne sont accessibles qu'à la fonction elle-même. On dit que ces variables sont des variables locales à la fonction.

En effet, chaque fois que la fonction est appelée, Python réserve pour elle (dans la mémoire de l'ordinateur) un nouvel espace de noms. Les contenus des variables locales sont stockés dans cet espace de noms qui est inaccessible depuis l'extérieur de la fonction. De plus, cet espace de noms est automatiquement détruit dès que la fonction a terminé son travail, donc si on l'appelle deux fois de suite elle recommence à zéro.

Les variables définies à l'extérieur d'une fonction sont des variables globales. Leur contenu est « visible » de l'intérieur d'une fonction, mais la fonction ne peut pas le modifier. Exemple :

>>> def mask():
...	  p = 20
...	  print p, q
...
>>> p, q = 15, 38
>>> mask()
20 38
>>> print p, q
15 38
Analysons attentivement cet exemple

Nous commençons par définir une fonction très simple (qui n'utilise d'ailleurs aucun paramètre). A l'intérieur de cette fonction, une variable p est définie, avec 20 comme valeur initiale. Cette variable p qui est définie à l'intérieur d'une fonction sera donc une variable locale.

Une fois terminée la définition de la fonction, nous revenons au niveau principal pour y définir les deux variables p et q auxquelles nous attribuons les contenus 15 et 38. Ces deux variables définies au niveau principal seront donc des variables globales.

Ainsi le même nom de variable p a été utilisé ici à deux reprises, pour définir deux variables différentes : l'une est globale et l'autre est locale. On peut constater dans la suite de l'exercice que ces deux variables sont bel et bien des variables distinctes, indépendantes, obéissant à une règle de priorité qui veut qu'à l'intérieur d'une fonction (où elles pourraient entrer en compétition), ce sont les variables définies localement qui ont la priorité.

On constate en effet que lorsque la fonction mask() est lancée, la variable globale q y est accessible, puisqu'elle est imprimée correctement. Pour p, par contre, c'est la valeur attribuée localement qui est affichée.

On pourrait croire d'abord que la fonction mask() a simplement modifié le contenu de la variable globale p (puisqu'elle est accessible). Les lignes suivantes démontrent qu'il n'en est rien : en dehors de la fonction mask(), la variable globale p conserve sa valeur initiale.

Cet état de choses peut toutefois être modifié si vous le souhaitez. Il peut se faire par exemple que vous ayez à définir une fonction qui soit capable de modifier une variable globale. Pour atteindre ce résultat, il vous suffira d'utiliser l'instruction "global". Cette instruction permet d'indiquer - à l'intérieur de la définition d'une fonction - quelles sont les variables à traiter globalement.

Autre exemple

Dans l'exemple ci-dessous, la variable à utiliser à l'intérieur de la fonction "monter()" est non seulement accessible, mais également modifiable, parce qu'elle est signalée explicitement comme étant une variable qu'il faut traiter globalement. Par comparaison, essayez le même exercice en supprimant l'instruction "global" : la variable "a" n'est plus incrémentée à chaque appel de la fonction.

>>> def monter():
...	global a
...	a = a+1
...	print a
...
>>> a = 15
>>> monter()
16
>>> monter()
17
>>>

Utilisation des fonctions dans un script[modifier | modifier le wikicode]

Pour cette première approche des fonctions, nous n'avons utilisé jusqu'ici que le mode interactif de l'interpréteur Python.

Il est bien évident que les fonctions peuvent aussi s'utiliser dans des scripts. Veuillez donc essayer vous-même le petit programme ci-dessous, lequel calcule le volume d'une sphère à l'aide de la formule que vous connaissez certainement :

def cube(n):
   return n**3

def volumeSphere(r):
   return 4 * 3.1416 * cube(r) / 3

r = input('Entrez la valeur du rayon : ')
print 'Le volume de cette sphère vaut', volumeSphere(r)
Notes

À bien y regarder, ce programme comporte trois parties : les deux fonctions cube() et volumeSphere(), et ensuite le corps principal du programme.

Dans le corps principal du programme, il y a un appel de la fonction volumeSphere().

À l'intérieur de la fonction volumeSphere(), il y a un appel de la fonction cube().

Notez bien que les trois parties du programme ont été disposées dans un certain ordre : d'abord la définition des fonctions, et ensuite le corps principal du programme. Cette disposition est nécessaire, parce que l'interpréteur exécute les lignes d'instructions du programme l'une après l'autre, dans l'ordre où elles apparaissent dans le code source. Dans le script, la définition des fonctions doit donc précéder leur utilisation.

Pour vous en convaincre, intervertissez cet ordre (en plaçant par exemple le corps principal du programme au début), et prenez note du type de message d'erreur qui est affiché lorsque vous essayez d'exécuter le script ainsi modifié.

En fait, le corps principal d'un programme Python constitue lui-même une entité un peu particulière, qui est toujours reconnue dans le fonctionnement interne de l'interpréteur sous le nom réservé __main__ (le mot main signifie « principal », en anglais. Il est encadré par des caractères « souligné » en double, pour éviter toute confusion avec d'autres symboles). L'exécution d'un script commence toujours avec la première instruction de cette entité __main__, où qu'elle puisse se trouver dans le listing. Les instructions qui suivent sont alors exécutées l'une après l'autre, dans l'ordre, jusqu'au premier appel de fonction. Un appel de fonction est comme un détour dans le flux de l'exécution : au lieu de passer à l'instruction suivante, l'interpréteur exécute la fonction appelée, puis revient au programme appelant pour continuer le travail interrompu. Pour que ce mécanisme puisse fonctionner, il faut que l'interpréteur ait pu lire la définition de la fonction avant l'entité __main__, et celle-ci sera donc placée en général à la fin du script.

Dans notre exemple, l'entité __main__ appelle une première fonction qui elle-même en appelle une deuxième. Cette situation est très fréquente en programmation. Si vous voulez comprendre correctement ce qui se passe dans un programme, vous devez donc apprendre à lire un script, non pas de la première à la dernière ligne, mais plutôt en suivant un cheminement analogue à ce qui se passe lors de l'exécution de ce script. Cela signifie concrètement que vous devrez souvent analyser un script en commençant par ses dernières lignes !

Modules de fonctions[modifier | modifier le wikicode]

Afin que vous puissiez mieux comprendre encore la distinction entre la définition d'une fonction et son utilisation au sein d'un programme, nous vous suggérons de placer fréquemment vos définitions de fonctions dans un module Python, et le programme qui les utilise dans un autre.

Exemple

On souhaite réaliser la série de dessins ci-dessous, à l'aide du module turtle :

Apprendre à programmer avec Python 9.png

Écrivez les lignes de code suivantes, et sauvegardez-les dans un fichier auquel vous donnerez le nom dessins_tortue.py :

from turtle import *
 
def carre(taille, couleur):
    "fonction qui dessine un carré de taille et de couleur déterminées"
    color(couleur)
    c =0
    while c <4:
        forward(taille)
        right(90)
        c = c +1

Vous pouvez remarquer que la définition de la fonction carre() commence par une chaîne de caractères. Cette chaîne ne joue aucun rôle fonctionnel dans le script : elle est traitée par Python comme un simple commentaire, mais qui est mémorisé à part dans un système de documentation interne automatique, lequel pourra ensuite être exploité par certains utilitaires et éditeurs « intelligents ».

Si vous programmez dans l'environnement IDLE, par exemple, vous verrez apparaître cette chaîne documentaire dans une « bulle d'aide », chaque fois que vous ferez appel aux fonctions ainsi documentées.

En fait, Python place cette chaîne dans une variable spéciale dont le nom est __doc__ (le mot « doc » entouré de deux paires de caractères « souligné »), et qui est associée à l'objet fonction comme étant l'un de ses attributs (vous en apprendrez davantage au sujet de ces attributs lorsque nous aborderons les classes d'objets).

Ainsi, vous pouvez vous-même retrouver la chaîne de documentation d'une fonction quelconque en affichant le contenu de cette variable. Exemple :

>>> def essai():
...     "Cette fonction est bien documentée mais ne fait presque rien."
...     print "rien à signaler"

>>> essai()
rien à signaler

>>> print essai.__doc__
Cette fonction est bien documentée mais ne fait presque rien.

Prenez donc la peine d'incorporer une telle chaîne explicative dans toutes vos définitions de fonctions futures : il s'agit là d'une pratique hautement recommandable.

Le fichier que vous aurez créé ainsi est dorénavant un véritable module de fonctions Python, au même titre que les modules turtle ou math que vous connaissez déjà. Vous pouvez donc l'utiliser dans n'importe quel autre script, comme celui-ci, par exemple, qui effectuera le travail demandé :

from dessins_tortue import *

up()                    # relever le crayon
goto(-150, 50)          # reculer en haut à gauche 

# dessiner dix carrés rouges, alignés :
i = 0
while i < 10:
    down()              # abaisser le crayon
    carre(25, 'red')    # tracer un carré
    up()                # relever le crayon
    forward(30)         # avancer + loin
    i = i +1

a = input()             # attendre
 vous pouvez à priori nommer vos modules de fonctions comme bon vous semble. Sachez cependant qu'il vous sera impossible d'importer un module si son nom est l'un des 29 mots réservés Python, car le nom du module importé deviendrait une variable dans votre script, et les mots réservés ne peuvent pas être utilisés comme noms de variables. Rappelons aussi qu'il vous faut éviter de donner à vos modules - et à tous vos scripts en général - le même nom que celui d'un module Python préexistant, sinon vous devez vous attendre à des conflits. Par exemple, si vous donnez le nom turtle.py à un exercice dans lequel vous avez placé une instruction d'importation du module "turtle", c'est l'exercice lui-même que vous allez importer !
Apprendre à programmer avec Python 10.png

Exercices

  1. 1.2.Définissez une fonction ligneCar(n, ca) qui renvoie une chaîne de n caractères ca.
  2. Définissez une fonction surfCercle(R). Cette fonction doit renvoyer la surface (l'aire) d'un cercle dont on lui a fourni le rayon R en argument. Par exemple, l'exécution de l'instruction :
    print surfCercle(2.5) doit donner le résultat 19.635
  3. Définissez une fonction volBoite(x1,x2,x3) qui renvoie le volume d'une boîte parallélipipédique dont on fournit les trois dimensions x1, x2, x3 en arguments. Par exemple, l'exécution de l'instruction :
    print volBoite(5.2, 7.7, 3.3) doit donner le résultat : 132.13
  4. Définissez une fonction maximum(n1,n2,n3) qui renvoie le plus grand de 3 nombres n1, n2, n3 fournis en arguments. Par exemple, l'exécution de l'instruction :
    print maximum(2,5,4) doit donner le résultat : 5
  5. Complétez le module de fonctions graphiques dessins_tortue.py.
    Commencez par ajouter un paramètre angle à la fonction carre(), de manière à ce que les carrés puissent être tracés dans différentes orientations. Définissez ensuite une fonction triangle(taille, couleur, angle) capable de dessiner un triangle équilatéral d'une taille, d'une couleur et d'une orientation bien déterminées.
    Testez votre module à l'aide d'un programme qui fera appel à ces fonctions à plusieurs reprises, avec des arguments variés pour dessiner une série de carrés et de triangles :
    Apprendre à programmer avec Python 11.png
  6. Ajoutez au module de l'exercice précédent une fonction etoile5() spécialisée dans le dessin d'étoiles à 5 branches. Dans votre programme principal, insérez une boucle qui dessine une rangée horizontale de de 9 petites étoiles de tailles variées :
    Apprendre à programmer avec Python 12.png
  7. Ajoutez au module de l'exercice précédent une fonction etoile6() capable de dessiner une étoile à 6 branches, elle-même constituée de deux triangles équilatéraux imbriqués. Cette nouvelle fonction devra faire appel à la fonction triangle() définie précédemment.
    Votre programme principal dessinera également une série de ces étoiles :
    Apprendre à programmer avec Python 13.png
    Apprendre à programmer avec Python 14.png
  8. Définissez une fonction compteCar(ca,ch) qui renvoie le nombre de fois que l'on rencontre le caractère ca dans la chaîne de caractères ch. Par exemple, l'exécution de l'instruction : print compteCar('e','Cette phrase est un exemple') doit donner le résultat : 7
  9. Définissez une fonction indexMax(liste) qui renvoie l'index de l'élément ayant la valeur la plus élevée dans la liste transmise en argument. Exemple d'utilisation :
    serie = [5, 8, 2, 1, 9, 3, 6, 7]
    print indexMax(serie)
    4
  10. Définissez une fonction nomMois(n) qui renvoie le nom du ne mois de l'année.
    Par exemple, l'exécution de l'instruction :
    print nomMois(4) doit donner le résultat : Avril
  11. Définissez une fonction inverse(ch) qui permette d'inverser les l'ordre des caractères d'une chaîne quelconque. (La chaîne inversée sera renvoyée au programme appelant).
  12. Définissez une fonction compteMots(ph) qui renvoie le nombre de mots contenus dans la phrase ph (On considère comme mots les ensembles de caractères inclus entre des espaces).

Solution

  1. Réfléchissez !
  2. from math import pi
    
    def surfCercle(r):
        "Surface d'un cercle de rayon r"
        return pi * r**2
    
    # test :
    print surfCercle(2.5)
    
  3. def volBoite(x1, x2, x3):
        "Volume d'une boîte parallélipipédique"
        return x1 * x2 * x3
    
    # test :
    print volBoite(5.2, 7.7, 3.3)
    
  4. def maximum(n1, n2, n3):
        "Renvoie le plus grand de trois nombres"
        if n1 >= n2 and n1 >= n3:
            return n1
        elif n2 >= n1 and n2 >= n3:
            return n2
        else:
            return n3
    
    # test :
    print maximum(4.5, 5.7, 3.9)
    
  5. Réfléchissez !
  6. Réfléchissez !
  7. Réfléchissez !
  8. def compteCar(ca, ch):
        "Renvoie le nombre de caractères ca trouvés dans la chaîne ch"
        i, tot = 0, 0
        while i < len(ch):
            if ch[i] == ca:
                tot = tot + 1
            i = i + 1
        return tot    
            
    # test :
    print compteCar("e","Cette chaîne est un exemple")
    
  9. def indexMax(tt):
        "renvoie l'indice du plus grand élément de la liste tt"
        i, max = 0, 0
        while i < len(tt):
            if tt[i] > max :
                max, imax = tt[i], i
            i = i + 1    
        return imax
    
    # test :
    serie = [5, 8, 2, 1, 9, 3, 6, 4]
    print indexMax(serie)
    
  10. def nomMois(n):
        "renvoie le nom du n-ième mois de l'année"
        mois = ['Janvier,', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet',
                'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre']
        return mois[n -1]       # les indices sont numérotés à partir de zéro
    
    # test :
    print nomMois(4)
    
  11. Réfléchissez !
  12. Réfléchissez !


Exercices

  1. Modifiez la fonction volBoite(x1,x2,x3) que vous avez définie dans un exercice précédent, de manière à ce qu'elle puisse être appelée avec trois, deux, un seul, ou même aucun argument. Utilisez pour ceux ci des valeurs par défaut égales à) 10.
    Par exemple :
    print volBoite() doit donner le résultat : 1000
    print volBoite(5.2) doit donner le résultat : 520.0
    print volBoite(5.2, 3) doit donner le résultat : 156.0
  2. Modifiez la fonction volBoite(x1,x2,x3) ci-dessus de manière à ce qu'elle puisse être appelée avec un, deux, ou trois arguments. Si un seul est utilisé, la boîte est considérée comme cubique (l'argument étant l'arête de ce cube). Si deux sont utilisés, la boîte est considérée comme un prisme à base carrée. (Dans ce cas le premier argument est le côté du carré, et le second la hauteur du prisme). Si trois arguments sont utilisés, la boîte est considérée comme un parallélépipède. Par exemple :
    print volBoite() doit donner le résultat : -1 (? indication d'une erreur).
    print volBoite(5.2) doit donner le résultat : 140.608
    print volBoite(5.2, 3) doit donner le résultat : 81.12
    print volBoite(5.2, 3, 7.4) doit donner le résultat : 115.44
  3. Définissez une fonction changeCar(ch,ca1,ca2,debut,fin) qui remplace tous les caractères ca1 par des caractères ca2 dans la chaîne de caractères ch, à partir de l'indice debut et jusqu'à l'indice fin, ces deux derniers arguments pouvant être omis (et dans ce cas la chaîne est traitée d'une extrémité à l'autre). Exemples de la fonctionnalité attendue :
    >>> phrase = 'Ceci est une toute petite phrase.'
    >>> print changeCar(phrase, ' ', '*')
    Ceci*est*une*toute*petite*phrase.
    >>> print changeCar(phrase, ' ', '*', 8, 12)
    Ceci est*une*toute petite phrase.
    >>> print changeCar(phrase, ' ', '*', 12)
    Ceci est une*toute*petite*phrase.
    >>> print changeCar(phrase, ' ', '*', fin = 12)
    Ceci*est*une*toute petite phrase.
    
  4. Définissez une fonction eleMax(liste,debut,fin) qui renvoie l'élément ayant la plus grande valeur dans la liste transmise. Les deux arguments debut et fin indiqueront les indices entre lesquels doit s'exercer la recherche, et chacun d'eux pourra être omis (comme dans l'exercice précédent). Exemples de la fonctionnalité attendue :
    >>> serie = [9, 3, 6, 1, 7, 5, 4, 8, 2]
    >>> print eleMax(serie)
    9
    >>> print eleMax(serie, 2, 5)
    7
    >>> print eleMax(serie, 2)
    8 
    >>> print eleMax(serie, fin =3, debut =1)
    6
    

Solution

  1. def volBoite(x1 =10, x2 =10, x3 =10):
        "Volume d'une boîte parallélipipédique"
        return x1 * x2 * x3
    
    # test :
    print volBoite()
    print volBoite(5.2)
    print volBoite(5.2, 3)
    
  2. def volBoite(x1 =-1, x2 =-1, x3 =-1):
        "Volume d'une boîte parallélipipédique"
        if x1 == -1 :
            return x1           # aucun argument n'a été fourni
        elif x2 == -1 :
            return x1**3        # un seul argument -> boîte cubique
        elif x3 == -1 :
            return x1*x1*x2     # deux arguments -> boîte prismatique
        else :
            return x1*x2*x3
    
    # test :
    print volBoite()
    print volBoite(5.2)
    print volBoite(5.2, 3)
    print volBoite(5.2, 3, 7.4)
    
  3. def changeCar(ch, ca1, ca2, debut =0, fin =-1):
        "Remplace tous les caractères ca1 par des ca2 dans la chaîne ch"
        if fin == -1:
            fin = len(ch)
        nch, i = "", 0            # nch : nouvelle chaîne à construire
        while i < len(ch) :
            if i >= debut and i <= fin and ch[i] == ca1:
                nch = nch + ca2
            else :
                nch = nch + ch[i]
            i = i + 1
        return nch
    
    # test :
    print changeCar("Ceci est une toute petite phrase", " ", "*")
    print changeCar("Ceci est une toute petite phrase", " ", "*", 8, 12)
    print changeCar("Ceci est une toute petite phrase", " ", "*", 12)
    
  4. def eleMax(lst, debut =0, fin =-1):
        "renvoie le plus grand élément de la liste lst"
        if fin == -1:
            fin = len(lst)
        max, i = 0, 0
        while i < len(lst):
            if i >= debut and i <= fin and lst[i] > max:
                max = lst[i]
            i = i + 1
        return max
    
    # test :
    serie = [9, 3, 6, 1, 7, 5, 4, 8, 2]
    print eleMax(serie)
    print eleMax(serie, 2)
    print eleMax(serie, 2, 5)
    


Modules

Définition[modifier | modifier le wikicode]

Vous avez déjà rencontré des fonctions intégrées au langage lui-même, comme la fonction len(), par exemple, qui permet de connaître la longueur d'une chaîne de caractères. Les fonctions intégrées au langage sont relativement peu nombreuses : ce sont seulement celles qui sont susceptibles d'être utilisées très fréquemment. Les autres sont regroupées dans des fichiers séparés que l'on appelle des modules.

Les modules sont donc des fichiers qui regroupent des ensembles de fonctions. En effet, il peut être commode de découper un programme important en plusieurs fichiers de taille modeste pour en faciliter la maintenance et le travail collectif. Une application Python typique sera alors constituée d'un programme principal accompagné de un ou plusieurs modules contenant chacun les définitions d'un certain nombre de fonctions accessoires.

Il existe un grand nombre de modules pré-programmés qui sont fournis d'office avec Python. Vous pouvez en trouver d'autres chez divers fournisseurs. Souvent on essaie de regrouper dans un même module des ensembles de fonctions apparentées que l'on appelle des bibliothèques.

Un module peut être appelé depuis plusieurs programmes, il s'agit d'un fichier .py commençant par son identité (qui ne contient pas de point).

N'importe quel fichier .py peut donc être appelé depuis un autre comme un module[1]. Il peut contenir :

du script
des fonctions
des classes
...

Importer un module[modifier | modifier le wikicode]

Pour utiliser des fonctions de modules dans un programme, il faut au début du fichier importer ceux-ci.

Pour ce faire, utiliser la commande "import" :

import os
import codecs

Sur la même ligne :

import os, codecs

Ou encore en sélectionnant tous les éléments d'un fichier :

from pywikibot import *

A noter : cette dernière méthode est dangereuse, car des objets du module portant le même nom que des objets du programme peuvent s'écraser l'un l'autre. Mieux vaut donc les nommer explicitement :

from pywikibot import pagegenerators

Le module math, par exemple, est fournit avec Python, et contient les définitions de nombreuses fonctions mathématiques telles que sinus, cosinus, tangente, racine carrée, etc. Pour pouvoir utiliser ces fonctions, il vous suffit d'incorporer la ligne suivante au début de votre script :

from math import *

Dans le corps du script lui-même, vous écrirez par exemple :

racine = sqrt(nombre) pour assigner à la variable "racine" la racine carrée de nombre, sinusx = sin(angle) pour assigner à la variable "sinusx" le sinus de angle (en radians !), etc.

Modules personnalisés[modifier | modifier le wikicode]

Pour créer son propre module et l'importer dans un autre fichier, il faut :

  • Soit que le module existe sous la forme d'un fichier .py situé dans le même dossier que le fichier qui l'importe. Exemple :
import Fichier1
Fichier1.fonction1()

Pour changer le préfixe :

import Fichier1 as F1
F1.fonction1()

Pour supprimer le préfixe :

from Fichier1 import *
fonction1()
  • Soit qu'il soit dans un autre dossier du programme, contenant un fichier __init__.py joutant le rôle de relais en important tous fichiers situés à côté de lui, ce qui permettra à toutes les fonctions de ce dossier d'être accessibles par le nom du dossier. Exemple dans dans un dossier "lib" :
from Fichier1 import *
from Fichier2 import *
from Fichier3 import *

__all__ = ["Fichier1", "Fichier2", "Fichier3"]

Dans le dossier parent :

import lib
fonction1()

Liste des modules standards[modifier | modifier le wikicode]

Les modules standards les plus importants sont[2] :

  • cgi
  • math
  • os
  • pickle
  • random
  • re
  • socket
  • sys
  • time
  • urllib

Exemple du module "math"[modifier | modifier le wikicode]

# Démo : utilisation des fonctions du module <math>

from math import *

nombre = 121
angle = pi/6	# soit 30° (la bibliothèque math inclut aussi la définition de pi) 
print 'racine carrée de', nombre, '=', sqrt(nombre)
print 'sinus de', angle, 'radians', '=', sin(angle)

L'exécution de ce script provoque l'affichage suivant :

racine carrée de 121 = 11.0
sinus de 0.523598775598 radians = 0.5

Ce court exemple illustre déjà fort bien quelques caractéristiques importantes des fonctions :

  • une fonction apparaît sous la forme d'un nom quelconque associé à des parenthèses. Exemple : sqrt()
  • dans les parenthèses, on transmet à la fonction un ou plusieurs arguments. Exemple : sqrt(121)
  • la fonction fournit une valeur de retour (on dira aussi qu'elle « renvoie » une valeur). Exemple : 11.0

Nous allons développer tout ceci dans les pages suivantes. Veuillez noter au passage que les fonctions mathématiques utilisées ici ne représentent qu'un tout premier exemple. Un simple coup d'œil dans la documentation des bibliothèques Python vous permettra de constater que de très nombreuses fonctions sont d'ores et déjà disponibles pour réaliser une multitude de tâches, y compris des algorithmes mathématiques très complexes (Python est couramment utilisé dans les universités pour la résolution de problèmes scientifiques de haut niveau). Il est donc hors de question de fournir ici une liste détaillée. Une telle liste est aisément accessible dans le système d'aide de Python :

Documentation HTML ® Python documentation ® Modules index ® math

Au chapitre suivant, nous apprendrons comment créer nous-mêmes de nouvelles fonctions.

Exercices

(Note : Dans tous ces exercices, utilisez la fonction raw_input() pour l'entrée des données)
  1. Écrivez un programme qui convertisse en mètres par seconde et en km/h une vitesse fournie par l'utilisateur en miles/heure. (Rappel : 1 mile = 1609 mètres)
  2. Écrivez un programme qui calcule le périmètre et l'aire d'un triangle quelconque dont l'utilisateur fournit les 3 côtés. (Rappel : l'aire d'un triangle quelconque se calcule à l'aide de la formule :
    dans laquelle d désigne la longueur du demi-périmètre, et a, b, c celles des trois côtés).
  3. Écrivez un programme qui calcule la période d'un pendule simple de longueur donnée. La formule qui permet de calculer la période d'un pendule simple est , l représentant la longueur du pendule et g la valeur de l'accélération de la pesanteur au lieu d'expérience.
  4. Écrivez un programme qui permette d'encoder des valeurs dans une liste. Ce programme devrait fonctionner en boucle, l'utilisateur étant invité à entrer sans cesse de nouvelles valeurs, jusqu'à ce qu'il décide de terminer en frappant <enter> en guise d'entrée. Le programme se terminerait alors par l'affichage de la liste. Exemple de fonctionnement :
    Veuillez entrer une valeur : 25
    Veuillez entrer une valeur : 18
    Veuillez entrer une valeur : 6284
    Veuillez entrer une valeur :
    [25, 18, 6284]
    

Solution

  1. # Conversion de miles/heure en km/h et m/s
    
    print "Veuillez entrer le nombre de miles parcourus en une heure : ",
    ch = raw_input()            # en général préférable à input()
    mph = float(ch)             # conversion de la chaîne entrée en nombre réel
    mps = mph * 1609 / 3600     # conversion en mètres par seconde
    kmph = mph * 1.609          # conversion en km/h
    # affichage :
    print mph, "miles/heure =", kmph, "km/h, ou encore", mps, "m/s"
    
  2. # Périmètre et Aire d'un triangle quelconque
    
    from math import sqrt
    
    print "Veuillez entrer le côté a : "
    a = float(raw_input())
    print "Veuillez entrer le côté b : "
    b = float(raw_input())
    print "Veuillez entrer le côté c : "
    c = float(raw_input())
    d = (a + b + c)/2                # demi-périmètre
    s = sqrt(d*(d-a)*(d-b)*(d-c))    # aire (suivant formule)
    
    print "Longueur des côtés =", a, b, c
    print "Périmètre =", d*2, "Aire =", s
    
  3. Réfléchissez !
  4. # Entrée d'éléments dans une liste
    
    tt = []             # Liste à compléter (vide au départ)
    ch = "start"        # valeur quelconque (mais non nulle) 
    while ch != "":
        print "Veuillez entrer une valeur : "
        ch = raw_input()
        if ch != "":
            tt.append(float(ch))        # variante : tt.append(ch)    
    
    # affichage de la liste :
    print tt
    

Références[modifier | modifier le wikicode]


Exercices sur les bases du langage

Révision[modifier | modifier le wikicode]

Dans ce qui suit, nous n'allons pas apprendre de nouveaux concepts mais simplement utiliser tout ce que nous connaissons déjà pour réaliser de vrais petits programmes.

Contrôle du flux - Utilisation d'une liste simple[modifier | modifier le wikicode]

Commençons par un petit retour sur les branchements conditionnels (il s'agit peut-être là du groupe d'instructions le plus important dans n'importe quel langage !) :

# Utilisation d'une liste et de branchements conditionnels

print ("Ce script recherche le plus grand de trois nombres")
print ('Veuillez entrer trois nombres séparés par des virgules : ')
# Note : la fonction list() convertit en liste la séquence de données qu'on
# lui fournit en argument. L'instruction ci-dessous convertira donc les
# données fournies par l'utilisateur en une liste  nn :
nn = list(input())
max, index = nn[0], 'premier'
if nn[1] > max:			# ne pas omettre le double point !
    max = nn[1]
    index = 'second'
if nn[2] > max:
    max = nn[2]
    index = 'troisième'
print ("Le plus grand de ces nombres est", max)
print ("Ce nombre est le", index, "de votre liste.")
 dans cet exercice, vous retrouvez à nouveau le concept de « bloc d'instructions », déjà abondamment commenté aux chapitres 3 et 4, et que vous devez absolument assimiler. Pour rappel, les blocs d'instructions sont délimités par l'indentation. Après la première instruction if, par exemple, il y a deux lignes indentées définissant un bloc d'instructions. Ces instructions ne seront exécutées que si la condition nn[1] > max est vraie.

La ligne suivante, par contre (celle qui contient la deuxième instruction if) n'est pas indentée. Cette ligne se situe donc au même niveau que celles qui définissent le corps principal du programme. L'instruction contenue dans cette ligne est donc toujours exécutée, alors que les deux suivantes (qui constituent encore un autre bloc) ne sont exécutées que si la condition nn[2] > max est vraie.

En suivant la même logique, on voit que les instructions des deux dernières lignes font partie du bloc principal et sont donc toujours exécutées.

Boucle while - Instructions imbriquées[modifier | modifier le wikicode]

Continuons dans cette voie en imbriquant d'autres structures :

 1 # Instructions composées <while> - <if> - <elif> - <else>               
 2 
 3 print 'Choisissez un nombre de 1 à 3 (ou zéro pour terminer) ',
 4 a = input()
 5 while a != 0:  # l'opérateur != signifie "différent de"
 6     if a == 1: 
 7         print "Vous avez choisi un :" 
 8         print "le premier, l'unique, l'unité ..." 
 9     elif a == 2: 
10         print "Vous préférez le deux :"
11         print "la paire, le couple, le duo ..."
12     elif a == 3:
13         print "Vous optez pour le plus grand des trois :"
14         print "le trio, la trinité, le triplet ..."
15     else :
16         print "Un nombre entre UN et TROIS, s.v.p."
17     print 'Choisissez un nombre de 1 à 3 (ou zéro pour terminer) ',
18     a = input()
19 print "Vous avez entré zéro :"
20 print "L'exercice est donc terminé."

Nous retrouvons ici une boucle while, associée à un groupe d'instructions if, elif et else.

L'instruction while est utilisée ici pour relancer le questionnement après chaque réponse de l'utilisateur (du moins jusqu'à ce que celui-ci décide de « quitter » en entrant une valeur nulle : rappelons à ce sujet que l'opérateur de comparaison != signifie « est différent de »). Dans le corps de la boucle, nous trouvons le groupe d'instructions if, elif et else (de la ligne 6 à la ligne 16), qui aiguille le flux du programme vers les différentes réponses, ensuite une instruction print et une instruction input() (lignes 17 & 18) qui seront exécutées dans tous les cas de figure : notez bien leur niveau d'indentation, qui est le même que celui du bloc if, elif et else, Après ces instructions, le programme boucle et l'exécution reprend à l'instruction while (ligne 5). Les deux dernières instructions print (lignes 19 & 20) ne sont exécutées qu'à la sortie de la boucle.


Exercices

  1. Que fait le programme ci-dessous, dans les quatre cas où l'on aurait défini au préalable que la variable a vaut 1, 2, 3 ou 15 ?
    if a !=2:
    	print 'perdu'
    elif a ==3:
    	print 'un instant, s.v.p.'
    else :
    	print 'gagné'
    
  2. Que font ces programmes ?
     a = 5
     b = 2
     if (a==5) & (b<2):
     print '"&" signifie "et"; on peut aussi utiliser le mot "and"'
    
     a, b = 2, 4
     if (a==4) or (b!=4):
     print 'gagné'
     elif (a==4) or (b==4):
     print 'presque gagné'
    
     a = 1
     if not a:
     print 'gagné'
     elif a:
     print 'perdu'
    
  3. Reprendre le programme c) avec a = 0 au lieu de a = 1. Que se passe-t-il ? Conclure !
  4. Écrire un programme qui, étant données deux bornes entières a et b, additionne les nombres multiples de 3 et de 5 compris entre ces bornes.
    Prendre par exemple a = 0, b = 32 ® le résultat devrait être alors 0 + 15 + 30 = 45.
    Modifier légèrement ce programme pour qu'il additionne les nombres multiples de 3 ou de 5 compris entre les bornes a et b. Avec les bornes 0 et 32, le résultat devrait donc être : 0 + 3 + 5 + 6 + 9 + 10 + 12 + 15 + 18 + 20 + 21 + 24 + 25 + 27 + 30 = 225.
  5. Déterminer si une année (dont le millésime est introduit par l'utilisateur) est bissextile ou non. (Une année A est bissextile si A est divisible par 4. Elle ne l'est cependant pas si A est un multiple de 100, à moins que A ne soit multiple de 400).
  6. Demander à l'utilisateur son nom et son sexe (M ou F). En fonction de ces données, afficher « Cher Monsieur » ou « Chère Mademoiselle » suivi du nom de l'élève.
  7. Demander à l'utilisateur d'entrer trois longueurs a, b, c. A l'aide de ces trois longueurs, déterminer s'il est possible de construire un triangle. Déterminer ensuite si ce triangle est rectangle, isocèle, équilatéral ou quelconque. Attention : un triangle rectangle peut être isocèle.
  8. Demander à l'utilisateur qu'il entre un nombre. Afficher ensuite : soit la racine carrée de ce nombre, soit un message indiquant que la racine carrée de ce nombre ne peut être calculée.
  9. Convertir une note scolaire N quelconque, entrée par l'utilisateur sous forme de points (par exemple 27 sur 85), en une note standardisée suivant le code suivant :
    Note Appréciation
    N >= 80 % A
    80 % > N >= 60 % B
    60 % > N >= 50 % C
    50 % > N >= 40 % D
    N < 40 % E
  10. Soit la liste suivante :
    ['Jean-Michel', 'Marc', 'Vanessa', 'Anne', 'Maximilien', 'Alexandre-Benoît', 'Louise']
    Ecrivez un script qui affiche chacun de ces noms avec le nombre de caractères correspondant.
  11. Écrire une boucle de programme qui demande à l'utilisateur d'entrer des notes d'élèves. La boucle se terminera seulement si l'utilisateur entre une valeur négative. Avec les notes ainsi entrées, construire progressivement une liste. Après chaque entrée d'une nouvelle note (et donc à chaque itération de la boucle), afficher le nombre de notes entrées, la note la plus élevée, la note la plus basse, la moyenne de toutes les notes.
  12. Ecrivez un script qui affiche la valeur de la force de gravitation s'exerçant entre deux masses de 10000 kg , pour des distances qui augmentent suivant une progression géométrique de raison 2, à partir de 5 cm (0,05 mètre). La force de gravitation est régie par la formule
    Exemple d'affichage :
    d = .05 m :  la force vaut  2.668 N
    d = .1 m  :  la force vaut  0.667 N
    d = .2 m  :  la force vaut  0.167 N
    d = .4 m  :  la force vaut  0.0417 N
    etc.
    

Solution

  1. Réfléchissez !
  2. Réfléchissez !
  3. Réfléchissez !
  4. # Traitement de nombres entiers compris entre deux limites
    
    print "Veuillez entrer la limite inférieure :",
    a = input()
    print "Veuillez entrer la limite supérieure :",
    b = input()
    s = 0                   # somme recherchée (nulle au départ)
    # Parcours de la série des nombres compris entre a et b :
    n = a                   # nombre en cours de traitement
    while n <= b:
        if n % 3 ==0 and n % 5 ==0:      # variante : 'or' au lieu de 'and'
            s = s + n
        n = n + 1
    
    print "La somme recherchée vaut", s
    
  5. # Années bissextiles
    
    print "Veuillez entrer l'année à tester :",
    a = input()
    
    if a % 4 != 0:
        # a n'est pas divisible par 4 -> année non bissextile
        bs = 0      
    else:
        if a % 400 ==0:
            # a divisible par 400 -> année bissextile
            bs = 1
        elif a % 100 ==0:
            # a divisible par 100 -> année non bissextile
            bs = 0
        else:
            # autres cas ou a est divisible par 4 -> année bissextile
            bs = 1
    if bs ==1:
        ch = "est"
    else:
        ch = "n'est pas"
    print "L'année", a, ch, "bissextile."
    
    Variante (proposée par Alex Misbah) :
    a=input('entrée une année:')
    
    if (a%4==0) and ((a%100!=0) or (a%400==0)):
        print a,"est une année bissextile"
    else:
        print a,"n'est pas une année bissextile"
    
    Variante (de Mik)
    a=input('année:')
    if (a%4==0 and a%100!=0)or(a%400==0):
        print "bi6"
    else:
        print "nbi6"
    
  6. Réfléchissez !
  7. from sys import exit      # module contenant des fonctions système
    
    print """
    Veuillez entrer les longueurs des 3 côtés
    (en séparant ces valeurs à l'aide de virgules) :"""
    a, b, c = input()
    # Il n'est possible de construire un triangle que si chaque côté
    # a une longueur inférieure à la somme des deux autres :
    if a < (b+c) and b < (a+c) and c < (a+b) :
        print "Ces trois longueurs déterminent bien un triangle."
    else:
        print "Il est impossible de construire un tel triangle !"
        exit()          # ainsi l'on n'ira pas plus loin. 
    
    f = 0
    if a == b and b == c :
        print "Ce triangle est équilatéral."
        f = 1
    elif a == b or b == c or c == a :
        print "Ce triangle est isocèle."
        f = 1
    if a*a + b*b == c*c or b*b + c*c == a*a or c*c + a*a == b*b :
        print "Ce triangle est rectangle."
        f = 1
    if f == 0 :
        print "Ce triangle est quelconque."
    
    Variante (de Mik)
    a,b= input('a:'),input('b:')
    if b>a:
        print '"c":](',b-a,');(',a+b,')['
    else:
        print '"c":](',a-b,');(',a+b,')['
    c=input('c:')
    if a < (b+c) and b < (a+c) and c < (a+b) :
        print 'bien un triangle'
    else:
        print 'impossible constrution triangle'
        exit()
    if a>b and a>c:
        max=a
        x=c*c+b*b
    elif b>a and b>c:
        max=b
        x=c*c+a*a
    elif c>b and c>a:
        max=c
        x=a*a+b*b
    if a==b and b==c :
        print "triangle équilatéral."
    elif a==b or b==c or c==a :
        print "triangle isocèle."
    elif x==max**2 :
        print "triangle rectangle."
    else:
        print "triangle quelconque."
    
  8. Réfléchissez !
  9. Réfléchissez !
  10. Réfléchissez !
  11. # Notes de travaux scolaires
    
    notes = []           # liste à construire  
    n = 2                # valeur positive quelconque pour initier la boucle
    while n >= 0 :
        print "Entrez la note suivante, s.v.p. : ",
        n = float(raw_input())      # conversion de l'entrée en un nombre réel
        if n < 0 :
            print "OK. Terminé."
        else:    
            notes.append(n)         # ajout d'une note à la liste
            # Calculs divers sur les notes déjà entrées :
            # valeurs minimale et maximale + total de toutes les notes. 
            min = 500               # valeur supérieure à toute note
            max, tot, i = 0, 0, 0        
            nn = len(notes)         # nombre de notes déjà entrées
            while i < nn:
                if notes[i] > max:
                    max = notes[i]
                if notes[i] < min:
                    min = notes[i]
                tot = tot + notes[i]
                moy = tot/nn
                i = i + 1
            print nn, "notes entrées. Max =", max, "Min =", min, "Moy =", moy
    
  12. Réfléchissez !

Exercices[modifier | modifier le wikicode]

Exercice 1[modifier | modifier le wikicode]

Écrire un programme qui affiche "Bonjour le monde".

Exercice 2[modifier | modifier le wikicode]

Écrire un programme qui permet de saisir le nom de l'utilisateur et de renvoyer "Bonjour", suivi de ce nom

Exercice 3[modifier | modifier le wikicode]

3. Écrire un programme qui demande à l'utilisateur la saisie de a et b et affiche la somme de a et de b.

Exercice 4[modifier | modifier le wikicode]

4. Écrire un programme qui demande à l'utilisateur son année de naissance et qui affiche son âge. L'année courante sera mise dans une variable.

Exercice 5[modifier | modifier le wikicode]

5. Écrire un programme qui demande à l'utilisateur les coordonnées de deux points dans le plan et qui calcule puis affiche la distance entre ces deux points selon la formule :



Regex

Les expressions régulières en Python nécessitent d'importer le module natif re[1], ou bien l'installation du module externe regex[2] si besoin des regex Unicode tels que \X.

Syntaxe[modifier | modifier le wikicode]

Expressions rationnelles courantes
Caractère Type Explication
. Point n'importe quel caractère
[...] crochets classe de caractères : tous les caractères énumérés dans la classe
[^...] crochets et circonflexe classe complémentée : tous les caractères sauf ceux énumérés
^ circonflexe marque le début de la chaine, la ligne...
$ dollar marque la fin d'une chaine, ligne...
| barre verticale alternative - ou reconnaît l'un ou l'autre
(...) parenthèses groupe de capture : utilisée pour limiter la portée d'un masque ou de l'alternative
* astérisque 0, 1 ou plusieurs occurrences
+ le plus 1 ou plusieurs occurrence
? interrogation 0 ou 1 occurrence
Classes de caractères POSIX[3]
Classe Signification
[[:alpha:]] n'importe quelle lettre
[[:digit:]] n'importe quel chiffre
[[:xdigit:]] caractères hexadécimaux
[[:alnum:]] n'importe quelle lettre ou chiffre
[[:space:]] n'importe quel espace blanc
[[:punct:]] n'importe quel signe de ponctuation
[[:lower:]] n'importe quelle lettre en minuscule
[[:upper:]] n'importe quelle lettre capitale
[[:blank:]] espace ou tabulation
[[:graph:]] caractères affichables et imprimables
[[:cntrl:]] caractères d'échappement
[[:print:]] caractères imprimables exceptés ceux de contrôle
Expressions rationnelles Unicode[4]
Expression Signification
\A Début de chaine
\b Caractère de début ou fin de mot
\d Chiffre
\D Non chiffre
\s Caractères espace
\S Non caractères espace
\W Caractère qui n'est pas lettre, chiffre ou underscore
\w Lettre, chiffre ou underscore
\X Caractère Unicode
\z Fin de chaine

Débogueur : https://regex101.com/

Remarques :

  • Les caractères de débuts et fin de chaines ne fonctionnent pas dans [].
  • Les opérateurs * et + sont toujours avides, pour qu'ils laissent la priorité il faut leur apposer un ? à leur suite.

De plus, Python propose :

  • la négation (?!). Attention : il faut toujours la faire suivre de .*. Exemple pour avoir toutes les balises HTML sauf "body" : <(?!body).*>.
  • Ignorer le groupe de capture dans la numérotation (?:)
  • negative lookbehind (?<!)
  • positive lookbehind (?<=)
  • negative lookahead (?!)
  • positive lookahead (?=)

Types[modifier | modifier le wikicode]

Les types de caractères sont représentés par :

  • \n : fin de ligne.
  • \b : fin de mot.
  • \w : caractère alphanumérique.
  • \d : caractère numérique.
  • \s : espace.

Certains ont leurs opposés en capitale :

  • \W : caractère non-alphanumérique.
  • \D : caractère non-numérique.
  • \S : non-espace.

Recherche[modifier | modifier le wikicode]

  • compile() renvoie None si l'expression rationnelle n'est pas trouvée dans la chaine.
  • search() renvoie la position des chaines recherchées.
#!/usr/bin/env python
import re
chaine = "Test regex Python pour Wikibooks francophone."
if re.compile('Wikibooks').search(chaine):
	print "Position du mot Wikibooks : "
	print re.search(u'Wikibooks', chaine).start()
        # Affiche "23"
        print re.search(u'Wikibooks', chaine).end()
        # Affiche "32"

Pour voir le pattern compilé : re.compile('Wikibooks').pattern

  • findall() trouve toutes les correspondances dans un tableau.
  • finditer() trouve toutes les correspondances dans un itérateur.
#!/usr/bin/env python
# Affiche tous les mots qui commencent par "Wiki"
import re
chaine = "Wikilivre regex Python pour Wikibooks francophone."
print (re.findall(r"Wiki\w+", chaine))
# Affiche ['Wikilivre', 'Wikibooks']


Les parenthèses imbriquées permettent d'indiquer des mots facultatifs au sein d'un groupe de capture. Ex :

#!/usr/bin/env python
# Trouve à un mot prêt
import re
chaine = "Wikilivre regex Python pour Wikibooks francophone."

regex = ur'(Python pour Wikibooks)'
print re.search(regex, chaine).start() # 16

regex = ur'(Python (pour )*Wikibooks)'
print re.search(regex, chaine).start() # 16

regex = ur'(Python pour (les )*Wikibooks)'
print re.search(regex, chaine).start() # 16

group()[modifier | modifier le wikicode]

Pour accéder aux résultats des groupes de capture, utiliser group() en partant de 1 (0 étant le match du pattern entier) :

#!/usr/bin/env python
import re
chaine = "Wikilivre regex Python pour Wikibooks francophone."
s = re.search(ur'(Wiki[a-z]*).*(Wiki[a-z]*)', chaine)
if s:
    print s.group(0)
    # Affiche 'Wikilivre regex Python pour Wikibooks'
    print s.group(1)
    # Affiche 'Wikilivre'
    print s.group(2)
    # Affiche 'Wikibooks'

Flags[modifier | modifier le wikicode]

Le comportement de certaines expressions peut être reconfiguré en ajoutant un "flag" en paramètre des méthodes[5].

re.IGNORECASE[modifier | modifier le wikicode]

Ignore la casse. Ainsi dans l'exemple précédent nous pouvions aussi faire :

 s = re.search(ur'(wiki[a-z]*).*(wiki[a-z]*)', chaine, re.IGNORECASE)

re.MULTILINE[modifier | modifier le wikicode]

Par défaut, les caractères "^" et "$" désignent le début et la fin de tout le texte. Or, en mode multiligne, un "^" en début de re.search() considérera le début de chaque ligne, et "$" leurs fins.

Pour partir uniquement du début de la chaine globale, il faut alors ne plus utiliser "re.search()" mais "re.match()"[6].

re.DOTALL[modifier | modifier le wikicode]

Par défaut, .* et .+ s'arrêtent aux retours chariot (\n). Pour qu'ils englobent ces retours à la ligne, il faut appeler re.DOTALL. Exemple :

 if re.search(regex, text, re.MULTILINE| re.DOTALL):

Remplacement[modifier | modifier le wikicode]

#!/usr/bin/env python
# Remplace tous les espaces par des underscores
import re
chaine = "Test regex Python pour Wikibooks francophone."
chaineTriee = re.sub(r' ', "_", chaine)
print chaineTriee
# Affiche "Test_regex_Python_pour_Wikibooks_francophone."

Pour remplacer certains éléments en conservant ceux placés entre parenthèses, il faut les désigner par \1, \2, \3...

#!/usr/bin/env python
# Ajoute des guillemets à tous les mots suivent "livre"
import re
chaine = "Test regex Python pour le livre Python de Wikibooks francophone."
chaineTriee = re.sub(r'(.*)livre (\w+)(.*)', r'\1livre "\2"\3', chaine)
print chaineTriee
# Affiche "Test regex Python pour le livre "Python" de Wikibooks francophone."

Remarque : si les paramètres (\1, \2...) sont remplacés par le symbole �, vérifier que la chaine regex est bien encodée avec r.

Attention !
link={{{link}}}

Les différents contenus d'un même groupe de capture sont remplacés par le premier \1. Pour éviter cela, il faut les traiter un par un avec "finditer()".

Exemple : remplacement de la balise "font color=" par "span style=font-size:".

    text = ur'<font color=green>Vert</font> / <font color=red>rouge</font>'
    regex = ur'<font color=([^>]*)>'
    pattern = re.compile(regex, re.UNICODE)
    for match in pattern.finditer(text):
        print u'Remplacement de ' + match.group(0) + u' par <span style="font-color:' + match.group(1) + u'">'
        text = text.replace(match.group(0), u'<span style="font-color:' + match.group(1) + u'">')
        text = text.replace('</font>', u'</span>')
    raw_input(text)

Exemples de formules[modifier | modifier le wikicode]

  • Récupérer le premier modèle 1 wiki non imbriquée dans un autre modèle :
page = u'{{Modèle2|Paramètre2, {{Modèle1|Paramètre3}} }}, {{Modèle1|Paramètre4}}'
regex = ur'({{(.*?)}}|.)*[^}]*'
raw_input(re.sub(regex, ur'\2', page).encode(config.console_encoding, 'replace'))

Pour indiquer un nombre précis d'occurrences, utiliser "{nombre}". Ex :

#!/usr/bin/env python
import re
chaine = 'w.1, ww.2, www.3, wwww.4'
print re.sub(ur' w{3}\.', ' http://www.', chaine)
w.1, ww.2, http://www.3, wwww.4

Idem pour une plage de nombres : {min,max}.

Attention !
link={{{link}}}

Quand on injecte une variable dans un pattern, il faut échapper ses caractères interprétables avec re.escape().

Références[modifier | modifier le wikicode]


Programmation orientée objet pour les non-programmeurs

Le concept objet[modifier | modifier le wikicode]

Dans les environnements de développement informatique, il a fallu attendre assez longtemps pour voir émerger le concept de l'objet. Son apparition a permis la création de systèmes beaucoup plus complexes mais aussi très empreints de mimétisme. En effet, dans notre monde réel, nous sommes tous entourés d'objets qui ont très souvent deux critères d'appréciation.

Le critère descriptif[modifier | modifier le wikicode]

Ce premier est universel, il contient toutes les caractéristiques qui décrivent l'objet. Nous prendrons comme exemple un dé, si nous avions à le décrire, nous dirions qu'il possède 6 faces avec un chiffre allant de 1 à 6 sur chacune d'elles, que la somme de deux valeurs étant sur des faces opposées vaut 7, que chaque chiffre entre un et six y est repris une et une seule fois, qu'il est (souvent) de couleur rouge et de petite taille. Il serait possible de le décrire plus précisément, mais en réalité, indiquer qu'il est fait de bois, que les nombres sont représentés par une quantité de point qui leur est égal, qu'il dispose de coin arrondi... n'aurait pas été plus éloquent.

Le critère d'interaction[modifier | modifier le wikicode]

Le deuxième critère est celui d'interaction, il indique l'utilité de l'objet, les possibilités qu'il vous offre. Pour le dé nous pourrions indiquer que celui-ci peut rouler, mais ce n'est pas son rôle. De même, dans certaines circonstances, celui-ci peut vous servir de cale, mais ici encore, nous nous éloignons du sujet. Objectivement, le dé a pour rôle de donner un nombre compris entre son minimum et son maximum (inclus) au hasard. D'ailleurs, on peut ajouter que cela arrive après l'avoir lancé.

l'héritage et l'implémentation[modifier | modifier le wikicode]

Ici, nous avons décrit un objet, et il nous suffit de faire de même en informatique. Mais nous pourrions approfondir la description en indiquant aussi que le dé est en fait dérivé d'un objet de base : le cube. Ainsi nous pourrions dire que le dé :

  • est un cube.
  • est de couleur rouge.
  • peut être lancé pour renvoyer un nombre compris entre 1 et 6 (le nombre de face qui le compose).

puis expliquer que le cube :

  • est un volume géométrique à trois dimensions.
  • est constitué de 6 carrés.

puis bien sûr qu'un carré :

  • est une figure géométrique à deux dimensions.


Et nous pourrions continuer précisant le terme dimension mais dans notre cas ce n'est pas utile. Nous pouvons ainsi établir le schémas suivant : le dé hérite des caractéristiques du cube (c'est un cube). Mais on ne peut pas dire que le cube hérite des caractéristiques du carré. En effet, on indique bien qu'il est constitué de mais pas qu'il est et c'est la toute la différence, vous êtes constitué de deux bras musclés mais vous n'êtes pas deux bras musclés (sauf si vous êtes déménageur... c'est une blague bien entendu, les déménageurs sont suffisamment allègre pour ne pas lancer un avis de recherche sur ma tête ) ! Nous dirons donc que :

  • l'objet cube implémente l'objet surface carré
  • l'objet hérite de l'objet cube

Un objet est une entité que l'on construit par instanciation à partir d'une classe (c'est-à-dire en quelque sorte une « catégorie » ou un « type » d'objet). Par exemple, on peut trouver dans la bibliothèque Tkinter, une classe Button() à partir de laquelle on peut créer dans une fenêtre un nombre quelconque de boutons.

Nous allons à présent examiner comment vous pouvez vous-mêmes définir de nouvelles classes d'objets. Il s'agit là d'un sujet relativement ardu, mais vous l'aborderez de manière très progressive, en commençant par définir des classes d'objets très simples, que vous perfectionnerez ensuite. Attendez-vous cependant à rencontrer des objets de plus en plus complexes par après.

Comme les objets de la vie courante, les objets informatiques peuvent être très simples ou très compliqués. Ils peuvent être composés de différentes parties, qui soient elles-mêmes des objets, ceux-ci étant faits à leur tour d'autres objets plus simples, etc.

Utilité des classes[modifier | modifier le wikicode]

Les classes sont les principaux outils de la programmation orientée objet ou POO (Object Oriented Programming ou OOP en anglais). Ce type de programmation permet de structurer les logiciels complexes en les organisant comme des ensembles d'objets qui interagissent, entre eux et avec le monde extérieur.

Le premier bénéfice de cette approche de la programmation consiste dans le fait que les différents objets utilisés peuvent être construits indépendamment les uns des autres (par exemple par des programmeurs différents) sans qu'il n'y ait de risque d'interférence. Ce résultat est obtenu grâce au concept d'encapsulation : la fonctionnalité interne de l'objet et les variables qu'il utilise pour effectuer son travail, sont en quelque sorte « enfermés » dans l'objet. Les autres objets et le monde extérieur ne peuvent y avoir accès qu'à travers des procédures bien définies.

En particulier, l'utilisation de classes dans vos programmes vous permettra - entre autres choses - d'éviter au maximum l'emploi de variables globales. Vous devez savoir en effet que l'utilisation de variables globales comporte des risques, surtout dans les programmes volumineux, parce qu'il est toujours possible que de telles variables soient modifiées ou même redéfinies n'importe où dans le corps du programme (et ce risque s'aggrave particulièrement si plusieurs programmeurs différents travaillent sur un même logiciel).

Un second bénéfice résultant de l'utilisation des classes est la possibilité qu'elles offrent de construire de nouveaux objets à partir d'objets préexistants, et donc de réutiliser des pans entiers d'une programmation déjà écrite (sans toucher à celle-ci !), pour en tirer une fonctionnalité nouvelle. Cela est rendu possible grâce aux concepts de dérivation et de polymorphisme.

  • La dérivation est le mécanisme qui permet de construire une classe « enfant » au départ d'une classe « parente ». L'enfant ainsi obtenu hérite toutes les propriétés et toute la fonctionnalité de son ancêtre, auxquelles on peut ajouter ce que l'on veut.
  • Le polymorphisme permet d'attribuer des comportements différents à des objets dérivant les uns des autres, ou au même objet ou en fonction d'un certain contexte.

La programmation orientée objet est optionnelle sous Python. Vous pouvez donc mener à bien de nombreux projets sans l'utiliser, avec des outils plus simples tels que les fonctions. Sachez cependant que les classes constituent des outils pratiques et puissants. Une bonne compréhension des classes vous aidera notamment à maîtriser le domaine des interfaces graphiques (Tkinter, wxPython), et vous préparera efficacement à aborder d'autres langages modernes tels que C++ ou Java.

Objet = [ attributs + méthodes ]

Cette façon d'associer dans une même « capsule » les propriétés d'un objet et les fonctions qui permettent d'agir sur elles, correspond chez les concepteurs de programmes à une volonté de construire des entités informatiques dont le comportement se rapproche du comportement des objets du monde réel qui nous entoure.

Considérons par exemple un widget « bouton ». Il nous paraît raisonnable de souhaiter que l'objet informatique que nous appelons ainsi ait un comportement qui ressemble à celui d'un bouton d'appareil quelconque dans le monde réel. Or la fonctionnalité d'un bouton réel (sa capacité de fermer ou d'ouvrir un circuit électrique) est bien intégrée dans l'objet lui-même (au même titre que d'autres propriétés telles que sa taille, sa couleur, etc.) De la même manière, nous souhaiterons que les différentes caractéristiques de notre bouton logiciel (sa taille, son emplacement, sa couleur, le texte qu'il supporte), mais aussi la définition de ce qui se passe lorsque l'on effectue différentes actions de la souris sur ce bouton, soient regroupés dans une entité bien précise à l'intérieur du programme, de manière telle qu'il n'y ait pas de confusion avec un autre bouton ou d'autres entités.



Classes

Définition d'une classe élémentaire[modifier | modifier le wikicode]

Pour créer une nouvelle classe d'objets Python, donc un nouveau type de donnée, on utilise l'instruction "class". Les définitions de classes peuvent être situées n'importe où dans un programme, mais on les placera en général au début (ou bien dans un module à importer).

Par exemple, nous allons maintenant créer un nouveau type composite : le type "Point". Ce type correspondra au concept de point en mathématiques. Dans un espace à deux dimensions, un point est caractérisé par deux nombres (ses coordonnées suivant x et y). En notation mathématique, on représente donc un point par ses deux coordonnées x et y enfermées dans une paire de parenthèses. On parlera par exemple du point (25, 17). Une manière naturelle de représenter un point sous Python serait d'utiliser pour les coordonnées deux valeurs de type float. Nous voudrions cependant combiner ces deux valeurs dans une seule entité, ou un seul objet. Pour y arriver, nous allons définir une classe Point() :

>>> class Point:
        "Définition d'un point mathématique"

Remarquons d'emblée que :

  • L'instruction class est un nouvel exemple d’instruction composée. Ce bloc doit contenir au moins une ligne. Dans notre exemple, cette ligne n'est rien d'autre qu'un simple commentaire. Par convention, si la première ligne suivant l'instruction class est une chaîne de caractères, celle-ci sera considérée comme un commentaire et incorporée automatiquement dans un dispositif de documentation des classes qui fait partie intégrante de Python. Prenez donc l'habitude de toujours placer une chaîne décrivant la classe à cet endroit.
  • Rappelez-vous aussi la convention qui consiste à toujours donner aux classes des noms qui commencent par une majuscule. Dans la suite de ce texte, nous respecterons encore une autre convention qui consiste à associer à chaque nom de classe une paire de parenthèses, comme nous le faisons déjà pour les noms de fonctions.

Nous pouvons dès à présent nous servir de cette classe pour créer des objets de ce type, par instanciation. Créons par exemple un nouvel objet p9.

 sous Python, on peut donc instancier un objet à l'aide d'une simple instruction d'affectation. D'autres langages imposent l'emploi d'une instruction spéciale, souvent appelée "new" pour bien montrer que l'on crée un nouvel objet à partir d'un moule. Exemple : p9 = new Point().
>>> p9 = Point()

Après cette instruction, la variable p9 contient la référence d'un nouvel objet Point(). Nous pouvons dire également que p9 est une nouvelle instance de la classe Point().

 comme les fonctions, les classes auxquelles on fait appel dans une instruction doivent toujours être accompagnées de parenthèses (même si aucun argument n'est transmis). Remarquez bien cependant que la définition d'une classe ne nécessite pas de parenthèses (contrairement à ce qui est de règle lors de la définition des fonctions), sauf si nous souhaitons que la classe en cours de définition dérive d'une autre classe préexistante.

Attributs (ou variables) d'instance[modifier | modifier le wikicode]

L'objet que nous venons de créer est une coquille vide. Nous pouvons ajouter des composants à cet objet par simple assignation, en utilisant le système de qualification des noms par points.

 ce système de notation est similaire à celui que nous utilisons pour désigner les variables d'un module, comme par exemple "math.pi" ou "string.uppercase". Les modules peuvent en effet contenir des fonctions, mais aussi des classes et des variables. Essayez par exemple :
import  string
print string.uppercase # ABCDEFGHIJKLMNOPQRSTUVWXYZ
print string.lowercase # abcdefghijklmnopqrstuvwxyz
print string.hexdigits # 0123456789abcdefABCDEF


Complétons la classe précédente avec les coordonnées d'un point :

class Point:
    x = 0
    y = 0

p9 = Point()
p9.x = 3.0
p9.y = 4.0
print (p9.x, p9.y)
(3.0, 4.0)
Schéma de variables d'instance

Les variables ainsi définies sont des attributs de l'objet p9, ou encore des variables d'instance. Elles sont incorporées, ou plutôt encapsulées dans l'objet. Le diagramme d'état ci-contre montre le résultat de ces affectations : la variable p9 contient la référence indiquant l'emplacement mémoire du nouvel objet, qui contient lui-même les deux attributs x et y.

On peut utiliser les attributs d'un objet dans n'importe quelle expression, comme toutes les variables ordinaires :

>>> print p9.x
3.0
>>> print p9.x**2 + p9.y**2	
25.0

Du fait de leur encapsulation dans l'objet, les attributs sont des variables distinctes d'autres variables qui pourraient porter le même nom. Par exemple, l'instruction x = p9.x signifie : « extraire de l'objet référencé par p9 la valeur de son attribut x, et assigner cette valeur à la variable x ».

Il n'y a pas de conflit entre la variable x et l'attribut x de l'objet p9. L'objet p9 contient en effet son propre espace de noms, indépendant de l'espace de nom principal où se trouve la variable x.

 nous venons de voir qu'il est très aisé d'ajouter un attribut à un objet en utilisant une simple instruction d'assignation telle que p9.x = 3.0. On peut se permettre cela sous Python (c'est une conséquence de l'assignation dynamique des variables), mais cela n'est pas vraiment recommandable. En effet, nous n'utiliserons cette façon de faire uniquement dans le but de simplifier nos explications concernant les attributs d'instances.

Passage d'objets comme arguments lors de l'appel d'une fonction[modifier | modifier le wikicode]

Les fonctions peuvent utiliser des objets comme paramètres (elles peuvent également fournir un objet comme valeur de retour). Par exemple, vous pouvez définir une fonction telle que celle-ci :

>>> def affiche_point(p):
        print "coord. horizontale =", p.x, "coord. verticale =", p.y

Le paramètre p utilisé par cette fonction doit être un objet de type Point(), puisque l'instruction qui suit utilise les variables d'instance p.x et p.y. Lorsqu'on appelle cette fonction, il faut donc lui fournir un objet de type Point() comme argument. Essayons avec l'objet p9 :

>>> affiche_point(p9)
coord. horizontale = 3.0 coord. verticale = 4.0

Exercices

  1. Ecrivez une fonction distance() qui permette de calculer la distance entre deux points. Cette fonction attendra évidemment deux objets Point() comme arguments.

Solution

  1. Réfléchissez !


Similitude et unicité[modifier | modifier le wikicode]

Dans la langue parlée, les mêmes mots peuvent avoir des significations fort différentes suivant le contexte dans lequel on les utilise. La conséquence en est que certaines expressions utilisant ces mots peuvent être comprises de plusieurs manières différentes (expressions ambiguës).

Le mot « même », par exemple, a des significations différentes dans les phrases : « Charles et moi avons la même voiture » et « Charles et moi avons la même mère ». Dans la première, ce que je veux dire est que la voiture de Charles et la mienne sont du même modèle. Il s'agit pourtant de deux voitures distinctes. Dans la seconde, j'indique que la mère de Charles et la mienne constituent en fait une seule et unique personne.

Lorsque nous traitons d'objets logiciels, nous pouvons rencontrer la même ambiguïté. Par exemple, si nous parlons de l'égalité de deux objets Point(), cela signifie-t-il que ces deux objets contiennent les mêmes données (leurs attributs), ou bien cela signifie-t-il que nous parlons de deux références à un même et unique objet ? Considérez par exemple les instructions suivantes :

>>> p1 = Point()
>>> p1.x = 3
>>> p1.y = 4
>>> p2 = Point()
>>> p2.x = 3
>>> p2.y = 4
>>> print (p1 == p2)
0

Ces instructions créent deux objets p1 et p2 qui restent distincts, même s'ils ont des contenus similaires. La dernière instruction teste l'égalité de ces deux objets (double signe égale), et le résultat est zéro (ce qui signifie que l'expression entre parenthèses est fausse : il n'y a donc pas égalité).

On peut confirmer cela d'une autre manière encore :

>>> print p1
<__main__.Point instance at 00C2CBEC>
>>> print p2
<__main__.Point instance at 00C50F9C>

L'information est claire : les deux variables p1 et p2 référencent bien des objets différents.


Essayons autre chose, à présent :

>>> p2 = p1
>>> print (p1 == p2)
1

Par l'instruction p2 = p1, nous assignons le contenu de p1 à p2. Cela signifie que désormais ces deux variables référencent le même objet. Les variables p1 et p2 sont des alias l'une de l'autre.

Le test d'égalité dans l'instruction suivante renvoie cette fois la valeur 1, ce qui signifie que l'expression entre parenthèses est vraie : p1 et p2 désignent bien toutes deux un seul et unique objet, comme on peut s'en convaincre en essayant encore :

>>> p1.x = 7
>>> print p2.x
7
>>> print p1
<__main__.Point instance at 00C2CBEC>
>>> print p2
<__main__.Point instance at 00C2CBEC>

Objets composés d'objets[modifier | modifier le wikicode]

Supposons maintenant que nous voulions définir une classe pour représenter des rectangles. Pour simplifier, nous allons considérer que ces rectangles seront toujours orientés horizontalement ou verticalement, et jamais en oblique.

De quelles informations avons-nous besoin pour définir de tels rectangles ? Il existe plusieurs possibilités. Nous pourrions par exemple spécifier la position du centre du rectangle (deux coordonnées) et préciser sa taille (largeur et hauteur). Nous pourrions aussi spécifier les positions du coin supérieur gauche et du coin inférieur droit. Ou encore la position du coin supérieur gauche et la taille. Admettons ce soit cette dernière méthode qui soit retenue.

Définissons donc notre nouvelle classe :

>>> class Rectangle:
        "définition d'une classe de rectangles"

... et servons nous-en tout de suite pour créer une instance :

>>> boite = Rectangle()
>>> boite.largeur = 50.0
>>> boite.hauteur = 35.0

Nous créons ainsi un nouvel objet Rectangle() et deux attributs. Pour spécifier le coin supérieur gauche, nous allons utiliser une instance de la classe Point() que nous avons définie précédemment. Ainsi nous allons créer un objet à l'intérieur d'un autre objet !

>>> boite.coin = Point()
>>> boite.coin.x = 12.0
>>> boite.coin.y = 27.0

Pour accéder à un objet qui se trouve à l'intérieur d'un autre objet, on utilise la qualification des noms hiérarchisée (à l'aide de points) que nous avons déjà rencontrée à plusieurs reprises. Ainsi l'expression boite.coin.y signifie « Aller à l'objet référencé dans la variable boite. Dans cet objet, repérer l'attribut coin, puis aller à l'objet référencé dans cet attribut. Une fois cet autre objet trouvé, sélectionner son attribut y. »

Vous pourrez peut-être mieux vous représenter à l'avenir les objets composites, à l'aide de diagrammes similaires à celui que nous reproduisons ci-dessous :

schéma de variables dans un contexte objet

Le nom « boîte » se trouve dans l'espace de noms principal. Il référence un autre espace de noms réservé à l'objet correspondant, dans lequel sont mémorisés les noms « largeur », « hauteur » et « coin ». Ceux-ci référencent à leur tour, soit d'autres espaces de noms (cas du nom « coin »), soit des valeurs bien déterminées. Python réserve des espaces de noms différents pour chaque module, chaque classe, chaque instance, chaque fonction. Vous pouvez tirer parti de tous ces espaces bien compartimentés afin de réaliser des programmes robustes, c'est-à-dire des programmes dont les différents composants ne peuvent pas facilement interférer.


Objets comme valeurs de retour d'une fonction[modifier | modifier le wikicode]

Nous avons vu plus haut que les fonctions peuvent utiliser des objets comme paramètres. Elles peuvent également transmettre une instance comme valeur de retour. Par exemple, la fonction trouveCentre() ci-dessous doit être appelée avec un argument de type Rectangle() et elle renvoie un objet Point(), lequel contiendra les coordonnées du centre du rectangle.

>>> def trouveCentre(box):
        p = Point()
        p.x = box.coin.x + box.largeur/2.0
        p.y = box.coin.y + box.hauteur/2.0
        return p

Pour appeler cette fonction, vous pouvez utiliser l'objet boite comme argument :

>>> centre = trouveCentre(boite)
>>> print centre.x, centre.y
37.0  44.5

Les objets sont modifiables[modifier | modifier le wikicode]

Nous pouvons changer les propriétés d'un objet en assignant de nouvelles valeurs à ses attributs. Par exemple, nous pouvons modifier la taille d'un rectangle (sans modifier sa position), en réassignant ses attributs hauteur et largeur :

>>> boite.hauteur = boite.hauteur + 20
>>> boite.largeur = boite.largeur – 5

Nous pouvons faire cela sous Python, parce que dans ce langage les propriétés des objets sont toujours publiques (du moins dans la version actuelle 2.0). D'autres langages établissent une distinction nette entre attributs publics (accessibles de l'extérieur de l'objet) et attributs privés (qui sont accessibles seulement aux algorithmes inclus dans l'objet lui-même).

Comme nous l'avons déjà signalé plus haut (à propos de la définition des attributs par assignation simple, depuis l'extérieur de l'objet), modifier de cette façon les attributs d'une instance n'est pas une pratique recommandable, parce qu'elle contredit l'un des objectifs fondamentaux de la programmation orientée objet, qui vise à établir une séparation stricte entre la fonctionnalité d'un objet (telle qu'elle a été déclarée au monde extérieur) et la manière dont cette fonctionnalité est réellement implémentée dans l'objet (et que le monde extérieur n'a pas à connaître).

Plus concrètement, nous devrons veiller désormais à ce que les objets que nous créons ne soient modifiables en principe que par l'intermédiaire de méthodes mises en place spécifiquement dans ce but, comme nous allons l'expliquer dans le chapitre suivant.


Définition d'une méthode[modifier | modifier le wikicode]

Pour illustrer notre propos, nous allons définir une nouvelle classe Time, qui nous permettra d'effectuer toute une série d'opérations sur des instants, des durées, etc. :

>>> class Time:
        "Définition d'une classe temporelle"

Créons à présent un objet de ce type, et ajoutons-lui des variables d'instance pour mémoriser les heures, minutes et secondes :

>>> instant = Time()
>>> instant.heure = 11
>>> instant.minute = 34
>>> instant.seconde = 25

À titre d'exercice, écrivez maintenant vous-même une fonction affiche_heure(), qui serve à visualiser le contenu d'un objet de classe Time() sous la forme conventionnelle « heure:minute:seconde ».

Appliquée à l'objet instant créé ci-dessus, cette fonction devrait donc afficher 11:34:25 :

>>> print affiche_heure(instant)
11:34:25

Votre fonction ressemblera probablement à ceci :

>>> def affiche_heure(t):
        print str(t.heure) + ":" + str(t.minute) + ":" + str(t.seconde)

(Notez au passage l'utilisation de la fonction str() pour convertir les données numériques en chaînes de caractères). Si par la suite vous utilisez fréquemment des objets de la classe Time(), il y a gros à parier que cette fonction d'affichage vous sera fréquemment utile.

Il serait donc probablement fort judicieux d'encapsuler cette fonction affiche_heure() dans la classe Time() elle-même, de manière à s'assurer qu'elle soit toujours automatiquement disponible chaque fois que l'on doit manipuler des objets de la classe Time().

Une fonction qui est ainsi encapsulée dans une classe s'appelle une méthode.


Définition concrète d'une méthode

On définit une méthode comme on définit une fonction, avec cependant deux différences :

  • La définition d'une méthode est toujours placée à l'intérieur de la définition d'une classe, de manière à ce que la relation qui lie la méthode à la classe soit clairement établie.
  • Le premier paramètre utilisé par une méthode doit toujours être une référence d'instance. Vous pourriez en principe utiliser un nom de variable quelconque pour ce paramètre, mais il est vivement conseillé de respecter la convention qui consiste à toujours lui donner le nom self. Le paramètre self désigne donc l'instance à laquelle la méthode sera associée, dans les instructions faisant partie de la définition. (De ce fait, la définition d'une méthode comporte toujours au moins un paramètre, alors que la définition d'une fonction peut n'en comporter aucun).

Voyons comment cela se passe en pratique :

Pour ré-écrire la fonction affiche_heure() comme une méthode de la classe Time(), il nous suffit de déplacer sa définition à l'intérieur de celle de la classe, et de changer le nom de son paramètre :

>>> class Time:
        "Nouvelle classe temporelle"
        def affiche_heure(self):
            print str(self.heure) + ":" + str(self.minute) \
                  + ":" + str(self.seconde)

La définition de la méthode fait maintenant partie du bloc d'instructions indentées après l'instruction class. Notez bien l'utilisation du mot réservé self, qui se réfère donc à toute instance susceptible d'être créée à partir de cette classe.


Essai de la méthode dans une instance

Nous pouvons dès à présent instancier un objet de notre nouvelle classe Time() :

>>> maintenant = Time()

Si nous essayons d'utiliser un peu trop vite notre nouvelle méthode, ça ne marche pas :

>>> maintenant.affiche_heure()
AttributeError: 'Time' instance has no attribute 'heure'

C'est normal : nous n'avons pas encore créé les attributs d'instance. Il faudrait faire par exemple :

>>> maintenant.heure = 13
>>> maintenant.minute = 34
>>> maintenant.seconde = 21
>>> maintenant.affiche_heure()
13:34:21

Nous avons cependant déjà signalé à plusieurs reprises qu'il n'est pas recommandable de créer ainsi les attributs d'instance en dehors de l'objet lui-même, ce qui conduit (entre autres désagréments) à des erreurs comme celle que nous venons de rencontrer, par exemple.

Voyons donc à présent comment nous pouvons mieux faire.

Méthodes prédéfinies[modifier | modifier le wikicode]

Certaines méthodes de classe Python existent automatiquement dans toutes les classes sans être déclarées, et certaines se lancent automatiquement lors de certains événements. Ces méthodes spéciales sont nommées entre deux underscores (__)[1].


__doc__[modifier | modifier le wikicode]

Comme pour les fonctions, la chaine de documentation est définie dans cette méthode.

>>> print p9.__doc__
Définition d'un point mathématique

__contains__[modifier | modifier le wikicode]

Cette méthode permet de lancer des recherches dans une classes comme dans un objet composite comme la liste, avec "in". En effet, il suffit d'y placer les getters sur les attributs :

class MyClass:
    attribute1 = 'ok'

    def __contains__(self, attribute):
        if self.attribute1: return True

MaClasse1 = MyClass()
print attribute1 in MaClasse1 # True
print attribute2 in MaClasse1 # False

__del__[modifier | modifier le wikicode]

Destructeur : se lance quand l'objet est détruit.


__enter__ et __exit__[modifier | modifier le wikicode]

Respectivement constructeur et destructeur des classes instanciées avec with, exécutés respectivement après et avant __init__ et __del__. Exemple :

class Test:        
    def __enter__(self):
        print 'enter'
     
    def __exit__(self, exc_type, exc_value, traceback):
        print 'exit'

with Test():
    pass
enter
exit


__ init __[modifier | modifier le wikicode]

Cette méthode se lance lors du premier accès à la classe.

Exemple :

class Complexe:
	def __init__(self, r, i):
		self.reel = r
		self.imaginaire = i

Complexe1 = Complexe(1, 2)
print Complexe1.reel    # Affiche 1


L'erreur que nous avons rencontrée au paragraphe précédent est-elle évitable ? Elle ne se produirait effectivement pas, si nous nous étions arrangés pour que la méthode affiche_heure() puisse toujours afficher quelque chose, sans qu'il ne soit nécessaire d'effectuer au préalable aucune manipulation sur l'objet nouvellement créé. En d'autres termes, il serait judicieux que les variables d'instance soient prédéfinies elles aussi à l'intérieur de la classe, avec pour chacune d'elles une valeur « par défaut ».

Pour obtenir cela, nous allons faire appel à une méthode particulière, que l'on appelle un constructeur. Une méthode constructeur est une méthode qui est exécutée automatiquement lorsque l'on instancie un nouvel objet à partir de la classe. On peut y placer tout ce qui semble nécessaire pour initialiser automatiquement l'objet que l'on crée.

Exemple :

>>> class Time:
        "Encore une nouvelle classe temporelle"
        def __init__(self):
            self.heure =0
            self.minute =0
            self.seconde =0

        def affiche_heure(self):
            print str(self.heure) + ":" + str(self.minute) \
                 + ":" + str(self.seconde)

>>> tstart = Time()
>>> tstart.affiche_heure()
0:0:0

L'intérêt de cette technique apparaîtra plus clairement si nous ajoutons encore quelque chose. Comme toute méthode qui se respecte, la méthode __init__() peut être dotée de paramètres. Ceux-ci vont jouer un rôle important, parce qu'ils vont permettre d'instancier un objet et d'initialiser certaines de ses variables d'instance, en une seule opération. Dans l'exemple ci-dessus, veuillez donc modifier la définition de la méthode __init__() comme suit :

        def __init__(self, hh =0, mm =0, ss =0):
            self.heure = hh
            self.minute = mm
            self.seconde = ss

La méthode __init__() comporte à présent 3 paramètres, avec pour chacun une valeur par défaut. Pour lui transmettre les arguments correspondants, il suffit de placer ceux-ci dans les parenthèses qui accompagnent le nom de la classe, lorsque l'on écrit l'instruction d'instanciation du nouvel objet.

Voici par exemple la création et l'initialisation simultanées d'un nouvel objet Time() :

>>> recreation = Time(10, 15, 18)
>>> recreation.affiche_heure()
10:15:18

Puisque les variables d'instance possèdent maintenant des valeurs par défaut, nous pouvons aussi bien créer de tels objets Time() en omettant un ou plusieurs arguments :

>>> rentree = Time(10, 30)
>>> rentree.affiche_heure()
10:30:0

__main__[modifier | modifier le wikicode]

>>> print p9
<__main__.Point instance at 0x403e1a8c>

Le message renvoyé par Python indique, comme vous l'aurez certainement bien compris tout de suite, que "p9" est une instance de la classe "Point()", qui est définie elle-même au niveau principal du programme. Elle est située dans un emplacement bien déterminé de la mémoire vive, dont l'adresse apparaît ici en notation hexadécimale.


__new__[modifier | modifier le wikicode]

Constructeur de métaclasse.


__repr__[modifier | modifier le wikicode]

Cette méthode renvoie une représentation de l'objet quand on l'appelle directement (sans chercher à accéder à ses attributs ou méthodes). Exemple :

class Bar:
    def __init__ (self, iamthis):
        self.iamthis = iamthis

    def __repr__(self):
        return "Bar('%s')" % self.iamthis

bar = Bar('apple')
print bar
Bar('apple')

Dans cette méthode, cet objet renverrait :

<__main__.Bar instance at 0x7f282bbf2a28>


__str__[modifier | modifier le wikicode]

Renvoie une chaine de caractères quand on traite l'objet comme tel. Exemple :

class Bar:
    def __init__ (self, iam_this):
        self.iam_this = iam_this

    def __str__ (self):
        return self.iam_this

bar = Bar('apple')
print bar
apple


__unicode__[modifier | modifier le wikicode]

Réservé à Python 2.x.


Opérateurs binaires[modifier | modifier le wikicode]

Fonction Opérateur
__add__ A + B
__sub__ A - B
__mul__ A * B
__truediv__ A / B
__floordiv__ A // B
__mod__ A % B
__pow__ A ** B
__and__ A & B
__or__ A | B
__xor__ A ^ B
__eq__ A == B
__ne__ A != B
__gt__ A > B
__lt__ A < B
__ge__ A >= B
__le__ A <= B
__lshift__ A << B
__rshift__ A >> B
__contains__ A in B
A not in B


Opérateurs unaires[modifier | modifier le wikicode]

Fonction Opérateur
__pos__ +A
__neg__ -A
__inv__ ~A
__abs__ abs(A)
__len__ len(A)


Gestion des attributs[modifier | modifier le wikicode]

Getters et setters.

Fonction Forme indirecte Forme directe
__getattr__ getattr(A, B) A.B
__setattr__ setattr(A, B, C) A.B = C
__delattr__ delattr(A, B) del A.B

Gestion des indices[modifier | modifier le wikicode]

Se déclenchent lorsque l'on manipule un objet comme un dictionnaire[2].

Fonction Opérateur
__getitem__ C[i]
__setitem__ C[i] = v
__delitem__ del C[i]
__getslice__ C[s:e]
__setslice__ C[s:e] = v
__delslice__ del C[s:e]


Divers[modifier | modifier le wikicode]

Fonction Opérateur
__cmp__ cmp(x, y)
__hash__ hash(x)
__nonzero__ bool(x)
__call__ f(x)
__iter__ iter(x)
__reversed__ reversed(x) (2.6+)
__divmod__ divmod(x, y)
__int__ int(x)
__long__ long(x)
__float__ float(x)
__complex__ complex(x)
__hex__ hex(x)
__oct__ oct(x)
__index__
__copy__ copy.copy(x)
__deepcopy__ copy.deepcopy(x)
__sizeof__ sys.getsizeof(x) (2.6+)
__trunc__ math.trunc(x) (2.6+)
__format__ format(x, ...) (2.6+)


Espaces de noms des classes et instances[modifier | modifier le wikicode]

Les variables définies à l'intérieur d'une fonction sont des variables locales, inaccessibles aux instructions qui se trouvent à l'extérieur de la fonction. Cela permet d'utiliser les mêmes noms de variables dans différentes parties d'un programme, sans risque d'interférence.

Pour décrire la même chose en d'autres termes, nous pouvons dire que chaque fonction possède son propre espace de noms, indépendant de l'espace de noms principal.

Les instructions se trouvant à l'intérieur d'une fonction peuvent accéder aux variables définies au niveau principal, mais en lecture seulement : elles peuvent utiliser les valeurs de ces variables, mais pas les modifier (à moins de faire appel à l'instruction global).

Il existe donc une sorte de hiérarchie entre les espaces de noms. Nous allons constater la même chose à propos des classes et des objets. En effet :

  • Chaque classe possède son propre espace de noms. Les variables qui en font partie sont appelées les attributs de la classe.
  • Chaque objet instance (créé à partir d'une classe) obtient son propre espace de noms. Les variables qui en font partie sont appelées variables d'instance ou attributs d'instance.
  • Les classes peuvent utiliser (mais pas modifier) les variables définies au niveau principal.
  • Les instances peuvent utiliser (mais pas modifier) les variables définies au niveau de la classe et les variables définies au niveau principal.

Considérons par exemple la classe Time() définie précédemment. À la page précédente, nous avons instancié deux objets de cette classe : recreation et rentree. Chacun a été initialisé avec des valeurs différentes, indépendantes. Nous pouvons modifier et réafficher ces valeurs à volonté dans chacun de ces deux objets, sans que l'autre n'en soit affecté :

>>> recreation.heure = 12
>>> rentree.affiche_heure()
10:30:0
>>> recreation.affiche_heure()
12:15:18

Veuillez à présent encoder et tester l'exemple ci-dessous :

>>> class Espaces:                          # 1
        aa = 33                             # 2
        def affiche(self):                  # 3
            print aa, Espaces.aa, self.aa   # 4

>>> aa = 12                                 # 5
>>> essai = Espaces()                       # 6
>>> essai.aa = 67                           # 7
>>> essai.affiche()                         # 8
12 33 67
>>> print aa, Espaces.aa, essai.aa          # 9
12 33 67

Dans cet exemple, le même nom aa est utilisé pour définir trois variables différentes : une dans l'espace de noms de la classe (à la ligne 2), une autre dans l'espace de noms principal (à la ligne 5), et enfin une dernière dans l'espace de nom de l'instance (à la ligne 7).

La ligne 4 et la ligne 9 montrent comment vous pouvez accéder à ces trois espaces de noms (de l'intérieur d'une classe, ou au niveau principal), en utilisant la qualification par points. Notez encore une fois l'utilisation de self pour désigner l'instance.

Héritage[modifier | modifier le wikicode]

Les classes constituent le principal outil de la programmation orientée objet ou POO (Object Oriented Programming ou OOP en anglais), qui est considérée de nos jours comme la technique de programmation la plus performante. L'un des principaux atouts de ce type de programmation réside dans le fait que l'on peut toujours se servir d'une classe préexistante pour en créer une nouvelle qui possédera quelques fonctionnalités différentes ou supplémentaires. Le procédé s'appelle dérivation. Il permet de créer toute une hiérarchie de classes allant du général au particulier.

Nous pouvons par exemple définir une classe Mammifere(), qui contiendra un ensemble de caractéristiques propres à ce type d'animal. A partir de cette classe, nous pourrons alors dériver une classe Primate(), une classe Rongeur(), une classe Carnivore(), etc., qui hériteront toutes des caractéristiques de la classe Mammifere(), en y ajoutant leurs spécificités.

Au départ de la classe Carnivore(), nous pourrons ensuite dériver une classe Belette(), une classe Loup(), une classe Chien(), etc., qui hériteront encore une fois toutes les caractéristiques de la classe Mammifere avant d'y ajouter les leurs. Exemple :

>>> class Mammifere:
        caract1 = "il allaite ses petits ;"

>>> class Carnivore(Mammifere):
        caract2 = "il se nourrit de la chair de ses proies ;"

>>> class Chien(Carnivore):
        caract3 = "son cri s'appelle aboiement ;"

>>> mirza = Chien()
>>> print mirza.caract1, mirza.caract2, mirza.caract3
il allaite ses petits ; il se nourrit de la chair de ses proies ;
son cri s'appelle aboiement ;

Dans cet exemple, nous voyons que l'objet mirza, qui est une instance de la classe Chien(), hérite non seulement l'attribut défini pour cette classe, mais également des attributs définis pour les classes parentes.

Vous voyez également dans cet exemple comment il faut procéder pour dériver une classe à partir d'une classe parente : On utilise l'instruction class, suivie comme d'habitude du nom que l'on veut attribuer à la nouvelle classe, et on place entre parenthèses le nom de la classe parente.

Notez bien que les attributs utilisés dans cet exemple sont des attributs des classes (et non des attributs d'instances). L'instance mirza peut accéder à ces attributs, mais pas les modifier :

1 >>> mirza.caract2 = "son corps est couvert de poils"
2 >>> print mirza.caract2
3 son corps est couvert de poils
4 >>> fido = Chien()
5 >>> print fido.caract2
6 il se nourrit de la chair de ses proies ;

Dans ce nouvel exemple, la ligne 1 ne modifie pas l'attribut caract2 de la classe Carnivore(), contrairement à ce que l'on pourrait penser au vu de la ligne 3. Nous pouvons le vérifier en créant une nouvelle instance fido (lignes 4 à 6).

Si vous avez bien assimilé les paragraphes précédents, vous aurez compris que l'instruction de la ligne 1 crée une nouvelle variable d'instance associée seulement à l'objet mirza. Il existe donc dès ce moment deux variables avec le même nom caract2 : l'une dans l'espace de noms de l'objet mirza, et l'autre dans l'espace de noms de la classe Carnivore().

Comment faut-il alors interpréter ce qui s'est passé aux lignes 2 et 3 ? Comme nous l'avons vu plus haut, l'instance mirza peut accéder aux variables situées dans son propre espace de noms, mais aussi à celles qui sont situées dans les espaces de noms de toutes les classes parentes. S'il existe des variables aux noms identiques dans plusieurs de ces espaces, laquelle sera-t-elle sélectionnée lors de l'exécution d'une instruction comme celle de la ligne 2 ?

Pour résoudre ce conflit, Python respecte une règle de priorité fort simple. Lorsqu'on lui demande d'utiliser la valeur d'une variable nommée alpha, par exemple, il commence par rechercher ce nom dans l'espace local (le plus « interne », en quelque sorte). Si une variable alpha est trouvée dans l'espace local, c'est celle-là qui est utilisée, et la recherche s'arrête. Sinon, Python examine l'espace de noms de la structure parente, puis celui de la structure grand-parente, et ainsi de suite jusqu'au niveau principal du programme.

À la ligne 2 de notre exemple, c'est donc la variable d'instance qui sera utilisée. À la ligne 5, par contre, c'est seulement au niveau de la classe grand-parente qu'une variable répondant au nom caract2 peut être trouvée. C'est donc celle-là qui est affichée.

Héritage et polymorphisme[modifier | modifier le wikicode]

Pour bien comprendre ce script, il faut cependant d'abord vous rappeler quelques notions élémentaires de chimie. Dans votre cours de chimie, vous avez certainement dû apprendre que les atomes sont des entités constituées d'un certain nombre de protons (particules chargées d'électricité positive), d'électrons (chargés négativement) et de neutrons (neutres).

Le type d'atome (ou élément) est déterminé par le nombre de protons, que l'on appelle également numéro atomique. Dans son état fondamental, un atome contient autant d'électrons que de protons, et par conséquent il est électriquement neutre. Il possède également un nombre variable de neutrons, mais ceux-ci n'influencent en aucune manière la charge électrique globale.

Dans certaines circonstances, un atome peut gagner ou perdre des électrons. Il acquiert de ce fait une charge électrique globale, et devient alors un ion (il s'agit d'un ion négatif si l'atome a gagné un ou plusieurs électrons, et d'un ion positif s'il en a perdu). La charge électrique d'un ion est égale à la différence entre le nombre de protons et le nombre d'électrons qu'il contient.

Le script suivant génère des objets atome et des objets ion. Nous avons rappelé ci-dessus qu'un ion est simplement un atome modifié. Dans notre programmation, la classe qui définit les objets « ion » sera donc une classe dérivée de la classe atome : elle héritera d'elle tous ses attributs et toutes ses méthodes, en y ajoutant les siennes propres. On pourra dire également que la méthode affiche() a été surchargée.

L'une de ces méthodes ajoutées (la méthode affiche()) remplace une méthode de même nom héritée de la classe atome. Les classes « atome » et « ion » possèdent donc chacune une méthode de même nom, mais qui effectuent un travail différent. On parle dans ce cas de polymorphisme. On pourra dire également que la méthode affiche() a été surchargée.

Il sera évidemment possible d'instancier un nombre quelconque d'atomes et d'ions à partir de ces deux classes. Or l'une d'entre elles (la classe atome) doit contenir une version simplifiée du tableau périodique des éléments (tableau de Mendeléev), de façon à pouvoir attribuer un nom d'élément chimique, ainsi qu'un nombre de neutrons, à chaque objet généré. Comme il n'est pas souhaitable de recopier tout ce tableau dans chacune des instances, nous le placerons dans un attribut de classe. Ainsi ce tableau n'existera qu'en un seul endroit en mémoire, tout en restant accessible à tous les objets qui seront produits à partir de cette classe.

Voyons concrètement comment toutes ces idées s'articulent :

class Atome:
    """atomes simplifiés, choisis parmi les 10 premiers éléments du TP""" 
    table = [None, ('hydrogène',0), ('hélium',2), ('lithium',4),
            ('béryllium',5), ('bore',6), ('carbone',6), ('azote',7),
            ('oxygène',8), ('fluor',10), ('néon',10)]
            
    def __init__(self, nat):
        "le n° atomique détermine le n. de protons, d'électrons et de neutrons" 
        self.np, self.ne = nat, nat       # nat = numéro atomique
        self.nn = Atome.table[nat][1]     # nb. de neutrons trouvés dans table
        
    def affiche(self):
        print
        print "Nom de l'élément :", Atome.table[self.np][0]
        print "%s protons, %s électrons, %s neutrons" % \
                  (self.np, self.ne, self.nn)
               
class Ion(Atome):
    """les ions sont des atomes qui ont gagné ou perdu des électrons"""
     
    def __init__(self, nat, charge):
        "le n° atomique et la charge électrique déterminent l'ion"
        Atome.__init__(self, nat)
        self.ne = self.ne - charge
        self.charge = charge
    
    def affiche(self):
        "cette méthode remplace celle héritée de la classe parente" 
        Atome.affiche(self)			# ... tout en l'utilisant elle-même ! 
        print "Particule électrisée. Charge =", self.charge        
        
### Programme principal : ###     

a1 = Atome(5)
a2 = Ion(3, 1)
a3 =