Initiation Via Python All
Initiation Via Python All
Initiation à la programmation
Xavier Dupré
http ://www.xavierdupre.fr/
Table des matières
1. Avant-propos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.1 Ordinateur et langages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2 Présentation du langage Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.3 Installation du langage Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.4 Installation d’un éditeur de texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.5 Premier programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.6 Installation d’extensions (ou modules externes) . . . . . . . . . . . . . . . . . . . . . . . . 23
2.7 Outils connexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
5. Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
5.1 Présentation des classes : méthodes et attributs . . . . . . . . . . . . . . . . . . . . . . . . 81
5.2 Constructeur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
5.3 Apport du langage Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
5.4 Opérateurs, itérateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
5.5 Méthodes, attributs statiques et ajout de méthodes . . . . . . . . . . . . . . . . . . . . . . 93
5.6 Copie d’instances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
TABLE DES MATIÈRES 3
6. Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
6.1 Principe des exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
6.2 Définir ses propres exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
6.3 Exemples d’utilisation des exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
7. Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
7.1 Modules et fichiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
7.2 Modules internes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
7.3 Modules externes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
7.4 Python et les autres langages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
7.5 Ecrire un module en langage C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
7.6 Boost Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Index 1012
Chapitre 1
Avant-propos
Quelques années passées à initier les élèves à l’informatique avec différents langages me poussent à dire
que le langage Python est sans doute un langage qui s’apprend plus vite sans pour autant être limité. Les
ordinateurs ont progressé et il n’est plus souvent nécessaire d’utiliser des langages tels que le C certes plus
rapide et plus connu mais aussi plus difficile à maîtriser. A partir de 2004, le langage Python a été utilisé
à l’ENSAE 1 pour initier les élèves à la programmation et, depuis cette date, j’ai pu observer un regain
d’intérêt des élèves pour cette matière qui s’appuyait auparavant sur le langage C. Certains étudiants
avouent même s’être amusés ; leur projet de programmation n’est plus centré sur un langage mais sur les
résultats qu’il permet d’obtenir.
Le langage Python suffit pour la plupart des besoins d’un ingénieur et permet de réaliser beaucoup plus
rapidement des programmes informatiques qui fonctionnent sur les principaux systèmes d’exploitation.
Internet fournit également un panel très large de librairies pour faire du calcul scientifique, des jeux ou
encore des sites Internet. Il suffit parfois de quelques minutes pour télécharger une extension et s’en servir.
Malgré ces avantages, il existe peu de livres de langue française sur ce langage, beaucoup moins que ceux
écrits en langue anglaise dont quelques uns seulement sont traduits.
Quelques d’ouvrages décrivent minutieusement le langage et ses extensions ([Swinnen2004], [Martelli2004],
[Pilgrim2004], [Ziadé2006]). L’ouvrage [Swinnen2004] part d’exemples pour expliquer le langage. Les trois
autres sont plus classiques dans leur présentation : les exemples sont moins présents et leur plan suit
plus les différentes fonctionnalités du langage. Un autre ouvrage ([Dayley2007]) prend une direction diffé-
rente : des explications courtes, beaucoup de courts exemples qui répondent à des besoins précis. Un livre
([Brucher2008]) s’intéresse à l’utilisation du langage que pourrait en faire un ingénieur : les fonctionnalités
liées au calcul numérique sont mieux représentées. Un dernier livre ([Bailly2008]) propose des exemples de
programmes équivalents rédigés en Python et C++ sans présenter de cas associant ces deux langages. J’ai
apprécié [Dayley2007] pour ses exemples concis, [Martelli2004] pour son exhaustivité. [Ziadé2006] est une
bonne référence pour ceux qui souhaitent prendre de bonnes habitudes de programmation.
Ce livre n’aborde pas des sujets comme la programmation web ou l’utilisation conjointe des langages
Python et SQL. La description du langage couvre les besoins qui sont ceux d’un ingénieur, c’est-à-dire une
personne dont la programmation ne constitue pas l’essentiel de son travail. Chaque notion est illustrée
par des exemples 2 . Ceux-ci sont particulièrement présents lors de l’introduction de notions pas toujours
évidentes à comprendre comme les threads, les interfaces graphiques et l’utilisation de C++. Le livre se
ferme sur plusieurs chapitres ne contenant que des exercices et leurs corrections. Ces exercices sont de
deux types : des travaux dirigés et des problèmes courts. Ces derniers ont été posés lors des examens à
l’ENSAE et ont été conçus pour préparer les élèves à répondre aux questions techniques lors des entretiens
d’embauche.
Le langage Python évolue assez vite, il est de plus en plus utilisé ce qui explique la multitude d’informations
qu’on peut trouver sur Internet. Le site officiel 3 recense la plupart des extensions (plus d’une centaine)
accessibles gratuitement. Il existe également de nombreux sites d’aide comme WikiPython 4 qui recense
des exemples de programmes sur des sujets variés. L’anglais est la langue d’échange par excellence dans le
monde informatique et le langage Python n’y échappe pas même si les moteurs de recherches retournent
1. Ecole Nationale de la Statistique et de l’Administration Economique, http://www.ensae.fr/
2. L’ensemble de ces exemples est accessible depuis le site http://www.xavierdupre.fr.
3. http://www.python.org/
4. http://wikipython.flibuste.net/
presque toujours des résultats en français pour des requêtes concernant Python, à condition toutefois d’y
insérer un mot de syntaxe exclusivement française.
Il n’est pas utile de lire tous les chapitres pour savoir programmer. Le chapitre 2 décrit l’installation du
langage Python et son utilisation via des éditeurs de texte. Les chapitres 3 et 4 introduisent les premiers
concepts, à partir de là, il est déjà possible d’écrire des programmes conséquents et notamment de lire les
chapitres 12 à 13 pour s’exercer.
Les chapitres 5 et 6 s’intéressent à la programmation objet, qui n’est pas indispensable dans un premier
temps. La programmation est utilisée en tant qu’outil pour atteindre un objectif, réaliser une étude ou
tester un modèle. Nombreux sont les élèves qui choisissent de contourner les classes et les objets sans pour
autant nuire à la qualité de leur travail ; les programmes qu’ils conçoivent sont sans doute moins lisibles
mais ils parviennent à l’objectif fixé.
Le chapitre 7 présente comment créer ses propres extensions. Les derniers paragraphes ne concernent que
des utilisateurs experts puisqu’ils parlent de l’utilisation conjointe des langages Python et C++ à partir
d’un exemple conçu à cet effet et utilisable en peu de temps 5 . Cette technique est intéressante dans des
domaines où les calculs doivent être impérativement très rapides comme en finance, matière à laquelle sont
formés les étudiants de l’ENSAE.
Le chapitre 8 introduit les fichiers où comment conservées des résultats sur disque dur. Le chapitre 9
présente les interfaces graphiques et le chapitre 10 les threads. Les chapitres 11 à 13 ne contiennent que
des exercices et problèmes sur lesquels plusieurs promotions de l’ENSAE ont été évaluées.
Visual Basic for Application (VBA)
Lorsqu’une application comme Excel est aussi couramment utilisée, il est parfois utile de savoir programmer
dans le langage associé à ce logiciel. Même s’il n’est pas toujours aussi convivial que Python, on y retrouve
les mêmes éléments (boucles, tests, fonctions). Néanmoins, comme Python, VBA est un langage assez lent et
il est aussi difficile de trouver des extensions de calcul numérique. C’est pourquoi, il est parfois utile de lier
les deux langages afin de pouvoir utiliser les nombreux modules disponibles pour le langage Python tels que
scipy ou encore BioPython. Le premier regroupe aborde le traitement du signal, l’estimation de densité, la
classification, l’optimisation... Le second module aborde des techniques spécifiques au domaine biologique
et plus spécifique les séquences ADN.
5. Concernant ce point, cet exemple téléchargeable permet de construire entièrement un module Python écrit en C++,
l’ajout d’une fonctionnalité ne prenant que quelques minutes. Cet exemple fonctionne sous Microsoft Windows avec Microsoft
Visual C++, il utilise la librairie Boost Python. Microsoft Windows est le système d’exploitation le plus courant dans les
sociétés.
Première partie
LE LANGAGE PYTHON
Les programmes informatiques sont souvent l’aboutissement d’un raisonnement, d’une construction, d’une
idée, parfois imprécise mais dont le principe général est compris. Et pour valider cette idée, on utilise un
langage de programmation qui ne tolère jamais l’imprécision, qui refuse de comprendre au moindre signe
de ponctuation oublié, qui est d’une syntaxe si rigide.
On reste parfois indécis devant une erreur qui se produit avec un exemple qu’on a pourtant recopié sans
ajout. On compare les deux versions sans faire attention aux petits détails qui ne changent rien pour le
concepteur et beaucoup pour le langage. C’est un espace en plus ou en moins, un symbole : oublié... Il
est fréquent de ne pas vérifier ces petits détails lorsqu’on commence à programmer. Et ils découragent
souvent. On s’habitue peu à peu au fait qu’il ne faut pas confondre parenthèses et crochets, qu’il manque
des guillemets, qu’il y a une lettre en plus, ou en moins.
Lorsque sa syntaxe n’est pas respectée, le langage de programmation ne cherche jamais à comprendre
l’intention du programmeur. Il faut penser à la vérifier en premier lorsqu’une erreur se produit. Les messages
d’erreur, obscurs au premier abord, donnent néanmoins un bon indice pour corriger un programme. Et si
cela ne suffisait pas, il ne faut pas hésiter à recopier ce message dans un moteur de recherche sur Internet
pour y trouver une indication dès les premiers résultats, et le plus souvent en français.
Cette première partie est consacrée à la description du langage Python. Il est parfois utile de reproduire
un des exemples, de le faire fonctionner, de le modifier, d’y introduire des erreurs puis de les corriger.
Plus tard, dans de plus longs programmes, les mêmes erreurs seront plus difficiles à déceler et l’expérience
montre qu’on fait presque toujours les mêmes erreurs.
Chapitre 2
Introduction
Ce chapitre s’intéresse tout d’abord à l’installation du langage Python et à la réalisation d’un premier pro-
gramme avec des instructions dont le sens est intuitif. Les derniers paragraphes présentent de nombreuses
extensions disponibles sur Internet. Elles rendent le langage Python très attractif dans des domaines variés.
Ces extensions témoignent que ce langage emporte l’adhésion de nombreux informaticiens qui en retour
assurent sa pérennité. Il permet de relier facilement différents éléments, différentes applications. C’est une
des raisons de son succès.
2.1.1 L’ordinateur
On peut considérer simplement qu’un ordinateur est composé de trois ensembles : le microprocesseur, la
mémoire, les périphériques. Cette description n’a pas varié en cinquante ans depuis qu’un scientifique du
nom de von Neumann l’a imaginée.
Le microprocesseur est le cœur de l’ordinateur, il suit les instructions qu’on lui donne et ne peut travailler
qu’avec un très petit nombre d’informations. Sa vitesse se mesure en GigaHertz (GHz) qui correspondent
au nombre d’opérations qu’il est capable d’effectuer en une seconde et en nombre de cœurs qui détermine
le nombre d’opérations en parallèle qu’il est capable d’exécuter. On lui adjoint une mémoire avec laquelle
il échange sans arrêt des données. Sa capacité se mesure en octets (kilo-octets, mégaoctets, gigaoctets ou
leurs abréviations Ko, Mo, Go 1 ). Ces échanges entre processeur et mémoire sont rapides.
Les périphériques regroupent tout le reste (écran, clavier, souris, disque dur, imprimante...). Ils sont princi-
palement de deux types : les périphériques de stockages (disque dur, DVD) et ceux qui nous permettent de
dialoguer avec l’ordinateur, que ce soit pour afficher, sonoriser (écran, enceintes) ou pour recevoir (souris,
clavier, webcam, micro...).
Leur écriture est indépendante du langage choisi, qu’il soit écrit en Basic, en Pascal, en C, en Perl, en PHP,
en Python, en français, un algorithme reste le même. Pour les algorithmes simples (un tri par exemple), le
passage d’un langage à l’autre consiste souvent à traduire mot-à-mot, ce qui favorise l’apprentissage d’un
nouveau langage informatique lorsqu’on en connaît déjà un. Les différences entre ces langages résident
dans leur spécialisation, le Visual Basic permet de piloter les applications Microsoft Office, le PHP, le
JavaScript sont dédiés à la programmation Internet. Le langage Python n’est pas spécialisé. Il est souvent
moins efficace que chaque langage appliqué à son domaine de prédilection mais il peut éviter l’apprentissage
d’une syntaxe différente.
Le langage Python n’est pas un langage compilé car un programme Python n’est pas traduit en langage
machine, il est un langage interprété. Entre son écriture et son exécution, il n’y a pas d’étape intermédiaire
telle que la compilation et on peut ainsi tester un programme plus rapidement même si son exécution est
alors plus lente.
La table 4.1 (page 52) regroupe les mots-clés du langage Python. Elle contient peu de mots-clés : son
concepteur s’est attaché à créer un langage objet avec la grammaire la plus simple possible.
Les instructions sont très courtes et tiennent sur une ligne mais si on n’en prend qu’une partie, elle perd
son sens. Ce serait comme considérer une phrase avec un verbe transitif mais sans son complément d’objet
direct.
distribué sous forme de logiciel libre. Python est couvert par sa propre licence 2 . Toutes les versions depuis
la 2.0.1 sont compatibles avec la licence GPL 3 . Selon Wikipedia 4 , Rossum travaillerait maintenant pour
l’entreprise Google qui propose une plate-forme de développement de sites web en Python 5 et qui héberge
de nombreux projets en langage Python via son projet Google Code 6 .
Perl, PHP, ...). Il est souvent possible de transposer les mêmes algorithmes d’un langage à un autre. Le
choix approprié est bien souvent celui qui offre la plus grande simplicité lors de la mise en œuvre d’un
programme même si cette simplicité s’acquiert au détriment de la vitesse d’exécution. Le langage PHP
est par exemple très utilisé pour la conception de sites Internet car il propose beaucoup de fonctions très
utiles dans ce contexte. Dans ce domaine, le langage Python est une solution alternative intéressante.
Comme la plupart des langages, le langage Python est tout d’abord portable puisqu’un même programme
peut être exécuté sur un grand nombre de systèmes d’exploitation comme Linux, Microsoft Windows,
Mac OS X... Python possède également l’avantage d’être entièrement gratuit tout en proposant la possi-
bilité de pouvoir réaliser des applications commerciales à l’aide de ce langage.
Si le langage C reste le langage de prédilection pour l’implémentation d’algorithmes complexes et gour-
mands en temps de calcul ou en capacités de stockage, un langage tel que Python suffit dans la plupart des
cas. De plus, lorsque ce dernier ne convient pas, il offre toujours la possibilité, pour une grande exigence de
rapidité, d’intégrer un code écrit dans un autre langage tel que le C/C++ 8 ou Java, et ce, d’une manière
assez simple. La question du choix du langage pour l’ensemble d’un projet est souvent superflue, il est cou-
rant aujourd’hui d’utiliser plusieurs langages et de les assembler. Le langage C reste incontournable pour
concevoir des applications rapides, en revanche, il est de plus en plus fréquent d’"habiller" un programme
avec une interface graphique programmée dans un langage tel que Python.
En résumé, l’utilisation du langage Python n’est pas restreinte à un domaine : elle comprend le calcul
scientifique, les interfaces graphiques, la programmation Internet. Sa gratuité, la richesse des extensions
disponibles sur Internet le rendent séduisant dans des environnements universitaire et professionnel. Le
langage est vivant et l’intérêt qu’on lui porte ne décroît pas. C’est un critère important lorsqu’on choisit
un outil parmi la myriade de projets open source. De plus, il existe différentes solutions pour améliorer
son principal point faible qui est la vitesse d’exécution.
La documentation (de langue anglaise 10 ) décrit en détail le langage Python, elle inclut également un
tutoriel 11 qui permet de le découvrir. La ligne de commande (voir figure 2.2) permet d’exécuter des
8. Ce point est d’ailleurs abordé au paragraphe 7.6, page 140.
9. Cette version est disponible à l’adresse http://www.python.org/download/. C’est la version utilisée pour développer les
exemples présents dans ce livre.
10. http://www.python.org/doc/
11. La requête python français de nombreux sites de documentation sur Python en français.
2. Introduction 16
instructions en langage Python. Elle est pratique pour effectuer des calculs mais il est nécessaire d’utiliser
un éditeur de texte pour écrire un programme, de le sauvegarder, et de ne l’exécuter qu’une fois terminé
au lieu que chaque ligne de celui-ci ne soit interprétée immédiatement après qu’elle a été écrite comme
c’est le cas pour une ligne de commande.
Figure 2.2 : Ligne de commande, la première ligne affecte la valeur 3 à la variable x, la seconde ligne l’affiche.
>>> x = 3
>>> y = 6
>>> z = x * y
>>> print z
18
>>>
Après l’exécution de ces quelques lignes, les variables 13 x, y, z existent toujours. La ligne de commande
ressemble à une calculatrice améliorée. Pour effacer toutes les variables créées, il suffit de redémarrer
12. voir la page http://www.python.org/download/mac/ ou http://www.python.org/download/linux/
13. Les variables sont définies au chapitre 3. En résumé, on peut considérer une variable comme une lettre, un mot qui
désigne une information. Dans cet exemple, les trois variables désignent des informations numériques qu’on peut manipuler
2. Introduction 17
l’interpréteur par l’intermédiaire du menu Shell–>Restart Shell. Les trois variables précédentes auront
disparu.
Il n’est pas possible de conserver le texte qui a été saisi au clavier, il est seulement possible de rappeler une
instruction déjà exécutée par l’intermédiaire de la combinaison de touches ALT + p, pressée une ou plusieurs
fois. La combinaison ALT + n permet de revenir à l’instruction suivante. Pour écrire un programme et ainsi
conserver toutes les instructions, il faut d’actionner le menu File–>New Window qui ouvre une seconde
fenêtre qui fonctionne comme un éditeur de texte (voir figure 2.4).
Après que le programme a été saisi, le menu Run→Run Module exécute le programme. Il demande au préalable
s’il faut enregistrer le programme et réinitialise l’interpréteur Python pour effacer les traces des exécutions
précédentes. Le résultat apparaît dans la première fenêtre (celle de la figure 2.3). La pression des touches
"Ctrl + C" permet d’arrêter le programme avant qu’il n’arrive à sa fin.
Remarque 2.7 : fenêtre intempestive
Si on veut se débarrasser de cette fenêtre intempestive qui demande confirmation pour enregistrer les
dernières modifications, il suffit d’aller dans le menu Options–>Configure IDLE et de choisir No prompt sur
la quatrième ligne dans la rubrique General (voir figure 2.5). Ce désagrément apparaît sur la plupart des
éditeurs de texte et se résout de la même manière.
Cette description succincte permet néanmoins de réaliser puis d’exécuter des programmes. Les autres
fonctionnalités sont celles d’un éditeur de texte classique, notamment la touche F1 qui débouche sur l’aide
associée au langage Python. Il est possible d’ouvrir autant de fenêtres qu’il y a de fichiers à modifier
simultanément.
comme si elles étaient effectivement des nombres. Les variables supprimées, les informations qu’elles désignaient ne plus
accessibles et sont perdues également.
2. Introduction 18
Néanmoins, il est préférable d’utiliser d’autres éditeurs plus riches comme celui proposé au paragraphe 2.4.1.
Ils proposent des fonctions d’édition plus évoluées que l’éditeur installé avec Python.
if PLAT_WIN
command.go.*.py=python -u "$(FileNameExt)"
command.go.subsystem.*.py=0
command.go.*.pyw=pythonw -u "$(FileNameExt)"
command.go.subsystem.*.pyw=1
Il suffit de préciser le répertoire où se trouve l’interpréteur qui devrait être c : /python26 sur Microsoft
Windows si le répertoire d’installation par défaut du langage Python n’a pas été modifié.
14. Cet éditeur est accessible depuis l’adresse http://www.scintilla.org/SciTE.html et téléchargeable depuis l’adresse http:
//scintilla.sourceforge.net/SciTEDownload.html.
15. Il arrive fréquemment que des universités, des sociétés interdisent à leurs utilisateurs l’installation de nouveaux logiciels
sur leurs machines pour des raisons de sécurité. Il faut des droits spécifiques pour contourner cette interdiction.
2. Introduction 19
if PLAT_WIN
command.go.*.py=c:\Python26\python -u "$(FileNameExt)"
command.go.subsystem.*.py=0
command.go.*.pyw=c:\Python26\pythonw -u "$(FileNameExt)"
command.go.subsystem.*.pyw=1
Une fois ce fichier enregistré, il ne reste plus qu’à écrire un programme Python. Une fois terminé, la touche
F5 lance son exécution. L’exemple de la figure 2.7 montre un cas où l’exécution a été interrompue par une
erreur.
Le site Internet de SciTe propose quelques trucs et astuces pour configurer l’éditeur à votre convenance.
Comme à peu près tous les logiciels, il dispose d’une rubrique FAQ 16 (Frequently Asked Questions) qui
recense les questions et les réponses les plus couramment posées. Cette rubrique existe pour la plupart des
éditeurs et plus généralement pour la plupart des applications disponibles sur Internet.
afin de vérifier chaque ligne de son exécution. Lorsqu’un programme produit de mauvais résultats, la
première solution consiste à afficher de nombreux résultats intermédiaires mais cela nécessite d’ajouter
des instructions un peu partout dans le programme. La seconde méthode est l’utilisation du débugger.
Sans modifier le code informatique, il est possible d’arrêter temporairement l’exécution à une ligne donnée
pour inspecter le contenu des variables à cet instant de l’exécution. Ce logiciel fonctionne sans autre
manipulation supplémentaire autre que son installation.
Cet éditeur, contrairement à SciTe, ne fonctionne qu’avec Python et ne peut être utilisé avec d’autres
langages. Son apparence est adaptée au développement. Il permet également de voir la liste des variables,
fonctions, classes, présentes dans un programme.
2.4.6 Tabulations
De nombreux éditeurs utilisent les tabulations pour mettre en forme un programme et tenir compte des
décalages (indentation) d’un bloc par rapport à un autre. Il est conseillé de remplacer ces tabulations par
des espaces, cela évite les confusions et les mauvaises interprétations lorsque tabulations et espaces sont
mélangés. La taille d’une tabulation peut varier d’un éditeur à l’autre contrairement aux espaces.
Un programme ne barbouille pas l’écran de texte indésirable, il n’affiche que ce que le programmeur lui
demande d’afficher et cette intention se matérialise grâce à l’instruction print. On peut ensuite écrire
quelques lignes qu’on pourrait également taper sur une calculatrice :
Ces deux lignes affichent 78.5398 qui est la surface d’un cercle de 5 mètres de côté. Le symbole ∗∗ correspond
à l’opération puissance. Il existe une constante PI ou π mais qui ne fait pas partie du langage lui-même : elle
est définie dans une extension interne 28 du langage qui contient bon nombre de fonctions mathématiques
telles que les cosinus, sinus...
Dans ce cas, il faut ajouter une ligne placée en première position qui précise que des accents pourront être
utilisés. L’exécution du programme qui suit ne soulève aucune erreur.
# coding: latin-1
print "accentué"
Cette ligne précise en fait que l’interpréteur Python doit utiliser un jeu de caractères spécial. Ces jeux de
caractères ont parfois leur importance, les navigateurs n’aiment pas trop les accents au sein des adresses
Internet : il est parfois préférable de ne pas utiliser d’accents sur les sites de réservations d’hôtels, de trains
ou d’avions.
Par défaut, l’interpréteur Python utilise le jeu de caractères le plus réduit, il faut lui préciser qu’il doit
en utiliser un plus étendu incluant les accents. On trouve également sous Microsoft Windows la syntaxe
équivalente suivante :
# coding: cp1252
print "accentué"
Enfin, s’il fallait utiliser des caractères autres que latins, il faudrait alors choisir le jeu de caractères utf − 8
qui s’appliquent aussi aux langues orientales.
# coding: utf-8
print "accentué"
A cause des accents, la plupart des exemples cités dans ce livre ne fonctionnent pas sans cette première
ligne qui a parfois été enlevée lors de l’impression pour des questions de lisibilité. Il faut penser à l’ajouter
pour reproduire les exemples. Le paragraphe 8.8 page 168 est plus complet à ce sujet.
Remarque 2.9 : #!/usr/local/bin/python
Sur Internet, on trouve de nombreux exemples commençant par la ligne suivante :
28. Cette extension est installée automatiquement avec Python contrairement à une extension externe.
2. Introduction 23
#!/usr/local/bin/python
On rencontre souvent cette ligne pour un programme écrit sur une machine Linux, elle indique l’emplace-
ment de l’interpréteur Python à utiliser. Cette ligne s’appelle un shebang.
2.6.1 Graphes
matplotlib 32 : ce module reprend la même logique que le logiciel MatLab ou Octave. Pour ceux
que la finance intéresse, il comporte également des fonctions qui permettent de récupérer des historiques
quotidiens de cours d’actions depuis le site Yahoo ! Finance 33 .
biggles 34 : ce module permet de dessiner des courbes (2D, 3D) et de convertir des graphiques sous
forme d’images de tout format. Ce module nécessite l’installation de fichiers supplémentaires (libpng, zlib,
plotutils) 35 .
chartdirector 36 : beaucoup plus rapide que MatPlotLib, ce module est gratuit à condition d’accepter un
bandeau jaune en bas de chaque graphique.
29. L’instruction help() saisie sur la ligne de commande Python retourne entre autres le numéro de version.
30. http://pypi.python.org/pypi
31. On peut citer http://wikipython.flibuste.net/ ou http://www.afpy.org/, deux sites français qui regroupent des informations
intéressantes sur de nouveaux modules ou des exemples d’utilisation de modules courants.
32. http://matplotlib.sourceforge.net/
33. Avec la fonction fetch_historical_yahoo.
34. http://biggles.sourceforge.net/
35. Accessibles depuis l’adresse http://www.gnu.org/software/plotutils/, ces informations sont disponibles depuis la page de
téléchargement de biggles.
36. http://www.advsofteng.com/
2. Introduction 24
pydot 37 : ce module propose le dessin de graphes dans une image (arbre généalogique, réseau de distribu-
tion, ...). Le module pydot permet de dessiner tout type de graphe. Ce module nécessite un autre module
pyparsing 38 et une application Graphviz 39 . Avec cet outil, on peut réaliser des graphes comme celui de
la figure 2.9. Ce module est utilisé lors de l’exercice 11.5.1 page 227.
pyx 40 : ce module est aussi une librairie qui permet de tracer des graphes avec la possibilité de convertir
directement ceux-ci en fichiers PDF ou EPS.
Sans utiliser nécessairement une extension, il existe des outils comme GNUPlot 41 venu du monde Linux
qui s’exécutent facilement en ligne de commande. Cet outil propose son propre langage de programmation
dédié à la création de graphiques. Une fois ce langage maîtrisé, il est facile de construire un programme
qui permet de l’exécuter en ligne de commande pour récupérer l’image du graphique.
Remarque 2.10 : sortie texte et graphique
Un des moyens simples de construire un rapport mélangeant résultats numériques et graphiques est de
construire un fichier au format HTML 42 puis de l’afficher grâce à un navigateur Internet. Il est même
possible de construire un fichier au format PDF en utilisant l’outil Latex 43 .
graphiques. Il faut au préalable installer Python et R puis le module Rpy fera la liaison entre les deux.
On pourrait également citer le module mdp 49 qui offre quelques fonctionnalités relatives à l’analyse des
données tels que l’analyse en composante principale (ACP) ou encore le module cvxopt 50 qui propose
des algorithmes d’optimisation quadratique sous contraintes.
2.6.3 Images
PythonImageLibrary(PIL) 51 : ce module permet d’utiliser les images, quelque soit leur format. Elle propose
également quelques traitements d’images simples, rotation, zoom, histogrammes.
ou deux pour écrire ses premiers programmes avec pygame. Il n’est pas prévu pour réaliser des jeux en 3D
mais suffit pour bon nombre de jeux de plateau, jeux de réflexion.
Pour la réalisation d’images et d’animations 3D, on peut utiliser le module pyOpenGL 59 qui s’interface avec
pygame, wxPython ou pyQt. C’est un module dont la maîtrise ne se compte plus en heures mais en dizaine
d’heures tout comme le module directpython 60 qui est l’équivalent de pyOpenGL mais uniquement sous
Microsoft Windows.
import psyco
psyco.full ()
Dans les faits, le programme s’exécute plus vite mais pas uniformément plus vite : les calculs sont le plus
favorisés. Toutefois, même avec ce module, le langage Python reste très lent par rapport à un langage
compilé comme le C++. L’outil Pyrex 64 propose une solution en permettant l’insertion de code C++ au
sein d’un programme Python. Pyrex n’est pas un module, c’est un interpréteur Python modifié pour
prendre en compte ces insertions C++. Il est essentiel de connaître la syntaxe du langage C++. Pyrex
propose des temps d’exécution tout à fait acceptable par rapport à ceux du C++ et il accroît fortement
la vitesse d’écriture des programmes. Son installation n’est pas toujours évidente car il faut le relier au
compilateur C++ GCC 65 . Une approche semblable est développée par l’extension Weave 66 du module
scipy 67 . Pyrex et Weave offre des performances bien supérieures à Python seul, proches de celle du
langage C. Weave conviendra sans doute mieux à ceux qui ont déjà programmé en C.
L’accélération de l’exécution d’un programme Python suscite l’intérêt de nombreux informaticiens, c’est
aussi l’objectif de l’outil PyPy 68 qui réécrit automatiquement certaines partie du code en langage C et
l’intègre au programme existant.
59. http://pyopengl.sourceforge.net/
60. http://sourceforge.net/projects/directpython/
61. http://python.net/crew/mhammond/win32/Downloads.html
62. comme http://wikipython.flibuste.net/CodeWindows#ExempleavecExcel
63. http://www.reportlab.com/software/opensource/rl-toolkit/
64. http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
65. http://gcc.gnu.org/, ce compilateur présent sur toute machine Linux est porté également sur Microsoft Windows (voir
le site http://www.mingw.org/).
66. http://www.scipy.org/Weave
67. http://www.scipy.org/
68. http://codespeak.net/pypy/dist/pypy/doc/home.html
2. Introduction 27
Zope 93 : c’est encore un outil pour concevoir des sites Internet, il est plus vieux et beaucoup plus riche. Il
est également plus complexe à appréhender. Il est plutôt destiné au développement de sites conséquents.
93. http://www.zope.org/
Chapitre 3
Types et variables du langage Python
3.1 Variables
Il est impossible d’écrire un programme sans utiliser de variable. Ce terme désigne le fait d’attribuer un
nom ou identificateur à des informations : en les nommant, on peut manipuler ces informations beaucoup
plus facilement. L’autre avantage est de pouvoir écrire des programmes valables pour des valeurs qui
varient : on peut changer la valeur des variables, le programme s’exécutera toujours de la même manière
et fera les mêmes types de calculs quelles que soient les valeurs manipulées. Les variables jouent un rôle
semblable aux inconnues dans une équation mathématique.
L’ordinateur ne sait pas faire l’addition de plus de deux nombres mais cela suffit à calculer la somme de
n premiers nombres entiers. Pour cela, il est nécessaire de créer une variable intermédiaire qu’on appellera
par exemple somme de manière à conserver le résultat des sommes intermédiaires.
somme = 0 # initialisation : la somme est nulle
for i in range(1,n) : # pour tous les indices de 1 à n exclu
somme = somme + i # on ajoute le i ème élément à somme
Comme le typage est dynamique en Python, le type n’est pas précisé explicitement, il est implicitement
liée à l’information manipulée. Par exemple, en écrivant, x = 3.4, on ne précise pas le type de la variable
x mais il est implicite car x reçoit une valeur réelle : x est de type réel ou float en Python. Pour leur
première initialisation, une variable reçoit dans la plupart des cas une constante :
Le langage Python possède un certain nombre de types de variables déjà définis ou types fondamentaux à
partir desquels il sera possible de définir ses propres types (voir chapitre 5). Au contraire de langages tels
que le C, il n’est pas besoin de déclarer une variable pour signifier qu’elle existe, il suffit de lui affecter
une valeur. Le type de la variable sera défini par le type de la constante qui lui est affectée. Le type d’une
variable peut changer, il correspond toujours au type de la dernière affectation.
x = 3.5 # création d’une variable nombre réel appelée x initialisée à 3.5
# 3.5 est un réel, la variable est de type "float"
sc = "chaîne" # création d’une variable chaîne de caractères appelée str
# initialisée à "chaîne", sc est de type "str"
3. Types et variables du langage Python 31
Avec ce symbole, les longues instructions peuvent être écrites sur plusieurs lignes de manière plus lisibles,
de sorte qu’elles apparaissent en entier à l’écran. Si le dernier caractère est une virgule, il est implicite.
Les paragraphes suivant énumèrent les types incontournables en Python. Ils sont classés le plus souvent en
deux catégories : types immuables ou modifiables. Tous les types du langage Python sont également des
objets, c’est pourquoi on retrouve dans ce chapitre certaines formes d’écriture similaires à celles présentées
plus tard dans le chapitre concernant les classes (chapitre 5).
Autrement dit, la simple instruction x+=3 qui consiste à ajouter à la variable x la valeur 3 crée une seconde
variable dont la valeur est celle de x augmentée de 3 puis à en recopier le contenu dans celui de la variable
x. Les nombres sont des types immuables tout comme les chaînes de caractères et les tuple qui sont des
tableaux d’objets. Il n’est pas possible de modifier une variable de ce type, il faut en recréer une autre du
même type qui intègrera la modification.
Certaines fonctions 1 utilisent cette convention lorsqu’il leur est impossible de retourner un résultat. Ce
n’est pas la seule option pour gérer cette impossibilité : il est possible de générer une exception 2 , de
retourner une valeur par défaut ou encore de retourner None. Il n’y a pas de choix meilleur, il suffit juste
de préciser la convention choisie.
1. Les fonctions sont définies au paragraphe 4.4, plus simplement, ce sont des mini-programmes : elles permettent de
découper un programme long en tâches plus petites. On les distingue des variables car leur nom est suivi d’une liste de
constantes ou variables comprises entre parenthèses et séparées par une virgule.
2. voir chapitre 6
3. Types et variables du langage Python 32
x = 3
y = 3.0
print "x =", x, type(x) x = 3 <type ’int’>
print "y =", y, type(y) y = 3.0 <type ’float’>
La liste des opérateurs qui s’appliquent aux nombres réels et entiers suit ce paragraphe. Les trois premiers
résultats s’expliquent en utilisant la représentation en base deux. 8 « 1 s’écrit en base deux 100 « 1 =
1000, ce qui vaut 16 en base décimale : les bits sont décalés vers la droite ce qui équivaut à multiplier par
deux. De même, 7&2 s’écrit 1011&10 = 10, qui vaut 2 en base décimale. Les opérateurs <<, >>, |, & sont
des opérateurs bit à bit, ils se comprennent à partir de la représentation binaire des nombres entiers.
Les fonctions int et float permettent de convertir un nombre quelconque ou une chaîne de caractères
respectivement en un entier (arrondi) et en un nombre réel.
x = int (3.5)
y = float (3)
z = int ("3")
print "x:", type(x), " y:", type(y), " z:", type(z)
# affiche x: <type ’int’> y: <type ’float’> z: <type ’int’>
Les opérateurs listés par le tableau ci-dessus ont des priorités différentes, triés par ordre croissant 3 . Tou-
tefois, il est conseillé d’avoir recours aux parenthèses pour enlever les doutes : 3 ∗ 2 ∗ ∗4 = 3 ∗ (2 ∗ ∗4).
Remarque 3.7 : division entière
Il existe un cas pour lequel cet opérateur cache un sens implicite : lorsque la division opère sur deux
nombres entiers ainsi que le montre l’exemple suivant.
3. La page http://docs.python.org/reference/expressions.html#operator-summary est plus complète à ce sujet.
3. Types et variables du langage Python 33
x = 11
y = 2
z = x / y # le résultat est 5 et non 5.5 car la division est entière
Pour obtenir le résultat juste incluant la partie décimale, il faut convertir les entiers en réels.
x = float (11)
y = float (2)
z = x / y # le résultat est 5.5 car c’est une division entre deux réels
Pour éviter d’écrire le type float, on peut également écrire 11.0/2 de façon à spécifier explicitement que la
valeur 11.0 est réelle et non entière. L’opérateur // permet d’effectuer une division entière lorsque les deux
nombres à diviser sont réels, le résultat est un entier mais la variable est de type réel si l’un des nombres
est de type réel.
3.2.3 Booléen
Les booléens sont le résultat d’opérations logiques et ont deux valeurs possibles : True ou False. Voici la
liste des opérateurs qui s’appliquent aux booléens.
x = 4 < 5
print x # affiche True
print not x # affiche False
Voici la liste des opérateurs de comparaisons qui retournent des booléens. Ceux-ci s’applique à tout type,
aux entiers, réels, chaînes de caractères, t-uples... Une comparaison entre un entier et une chaîne de
caractères est syntaxiquement correcte même si le résultat a peu d’intérêt.
A l’instar des nombres réels, il est préférable d’utiliser les parenthèses pour éviter les problèmes de priorités
d’opérateurs dans des expressions comme : 3 < x and x < 7. Toutefois, pour cet exemple, Python accepte
l’écriture résumée qui enchaîne des comparaisons : 3 < x and x < 7 est équivalent à 3 < x < 7. Il existe deux
autres mots-clés qui retournent un résultat de type booléen :
opérateur signification
is test d’identification
in test d’appartenance
Ces deux opérateurs seront utilisés ultérieurement, in avec les listes, les dictionnaires, les boucles (para-
graphe 4.3.2), is lors de l’étude des listes (paragraphe 3.3.2) et des classes (chapitre 5). Bien souvent, les
booléens sont utilisés de manière implicite lors de tests (paragraphe 4.2.1) ce qui n’empêche pas de les
déclarer explicitement.
x = True
y = False
3. Types et variables du langage Python 34
Ce texte est compris entre deux guillemets ou deux apostrophes, ces deux symboles sont interchangeables.
L’exemple suivant montre comment créer une chaîne de caractères. Il ne faut pas confondre la partie entre
guillemets ou apostrophes, qui est une constante, de la variable qui la contient.
t = "string = texte"
print type (t), t
t = ’string = texte, initialisation avec apostrophes’
print type (t), t
t = "morceau 1" \
"morceau 2" # second morceau ajouté au premier par l’ajout du symbole \,
# il ne doit rien y avoir après le symbole \,
# pas d’espace ni de commentaire
print t
t = """première ligne
seconde ligne""" # chaîne de caractères qui s’étend sur deux lignes
print t
La troisième chaîne de caractères créée lors de ce programme s’étend sur deux lignes. Il est parfois plus com-
mode d’écrire du texte sur deux lignes plutôt que de le laisser caché par les limites de fenêtres d’affichage.
Python offre la possibilité de couper le texte en deux chaînes de caractères recollées à l’aide du symbole \
à condition que ce symbole soit le dernier de la ligne sur laquelle il apparaît. De même, lorsque le texte
contient plusieurs lignes, il suffit de les encadrer entre deux symboles """ ou ”’ pour que l’interpréteur
Python considère l’ensemble comme une chaîne de caractères et non comme une série d’instructions.
Par défaut, le Python ne permet pas l’insertion de caractères tels que les accents dans les chaînes de
caractères, le paragraphe 2.5.2 (page 22) explique comment résoudre ce problème. De même, pour insérer
un guillemet dans une chaîne de caractères encadrée elle-même par des guillemets, il faut le faire précéder
du symbole \. La séquence \” est appelée un extra-caractère (voir table 3.1).
\” guillemet
\0 apostrophe
\n passage à la ligne
\\ insertion du symbole \
\% pourcentage, ce symbole est aussi un caractère spécial
\t tabulation
\r
retour à la ligne, peu usité, il a surtout son importance lorsqu’on passe d’un système Windows à
Linux car Windows l’ajoute automatiquement à tous ses fichiers textes
Table 3.1 : Liste des extra-caractères les plus couramment utilisés à l’intérieur d’une chaîne de caractères (voir
page http:// docs.python.org/ reference/ lexical_analysis.html#strings).
3. Types et variables du langage Python 35
Sans la lettre "r", tous les \ doivent être doublés, dans le cas contraire, Python peut avoir des effets
indésirables selon le caractère qui suit ce symbole.
Une chaîne de caractères est semblable à un tableau et certains opérateurs qui s’appliquent aux tableaux
s’appliquent également aux chaînes de caractères. Ceux-ci sont regroupés dans la table 3.2. La fonction
str permet de convertir un nombre, un tableau, un objet (voir chapitre 5) en chaîne de caractères afin de
pouvoir l’afficher. La fonction len retourne la longueur de la chaîne de caractères.
x = 5.567
s = str (x)
print type(s), s # <type ’str’> 5.567
print len(s) # affiche 5
Où s est une chaîne de caractères, fonction est le nom de l’opération que l’on veut appliquer à s,
res est le résultat de cette manipulation.
La table 3.3 (page 36) présente une liste non exhaustive des fonctions disponibles dont un exemple d’uti-
lisation suit. Cette syntaxe variable.fonction(arguments) est celle des classes 4 .
4. voir chapitre 5
3. Types et variables du langage Python 36
st = "langage python"
st = st.upper () # mise en lettres majuscules
i = st.find ("PYTHON") # on cherche "PYTHON" dans st
print i # affiche 8
print st.count ("PYTHON") # affiche 1
print st.count ("PYTHON", 9) # affiche 0
L’exemple suivant permet de retourner une chaîne de caractères contenant plusieurs éléments séparés par
”; ”. La chaîne ”un; deux; trois” doit devenir ”trois; deux; un”. On utilise pour cela les fonctionnalités split
et join (voir table 3.3). L’exemple utilise également la fonctionnalité reverse des listes qui seront décrites
plus loin dans ce chapitre. Il faut simplement retenir qu’une liste est un tableau. reverse retourne le
tableau.
s = "un;deux;trois"
mots = s.split (";") # mots est égal à [’un’, ’deux’, ’trois’]
mots.reverse () # retourne la liste, mots devient égal à
# [’trois’, ’deux’, ’un’]
s2 = ";".join (mots) # concaténation des éléments de mots séparés par ";"
print s2 # affiche trois;deux;un
Python offre une manière plus concise de former une chaîne de caractères à l’aide de plusieurs types
d’informations en évitant la conversion explicite de ces informations (fonction str) et leur concaténation.
Il est particulièrement intéressant pour les nombres réels qu’il est possible d’écrire en imposant un nombre
3. Types et variables du langage Python 37
c1 est un code choisi parmi ceux de la table 3.4 (page 37). Il indique le format dans lequel la variable
v1 devra être transcrite. Il en est de même pour le code c2 associé à la variable v2. Les codes insérés
dans la chaîne de caractères seront remplacés par les variables citées entre parenthèses après le
symbole % suivant la fin de la chaîne de caractères. Il doit y avoir autant de codes que de variables,
qui peuvent aussi être des constantes.
La seconde affectation de la variable res propose une solution équivalente à la première en utilisant
l’opérateur de concaténation +. Les deux solutions sont équivalentes, tout dépend des préférences de celui
qui écrit le programme.
un nombre réel 5.500000 et un entier 7, une chaîne de caractères,
un réel d’abord converti en chaîne de caractères 9.5
un nombre réel 5.5 et un entier 7, une chaîne de caractères,
un réel d’abord converti en chaîne de caractères 9.5
La première option permet néanmoins un formatage plus précis des nombres réels en imposant par exemple
un nombre défini de décimal. Le format est le suivant :
où n est le nombre de chiffres total et d est le nombre de décimales, f désigne un format réel indiqué
par la présence du symbole %
x = 0.123456789
print x # affiche 0.123456789
print "%1.2f" % x # affiche 0.12
print "%06.2f" % x # affiche 000.12
Il existe d’autres formats regroupés dans la table 3.4. L’aide reste encore le meilleur réflexe car le langage
Python est susceptible d’évoluer et d’ajouter de nouveaux formats.
d entier relatif
e nombre réel au format exponentiel
f nombre réel au format décimal
g nombre réel, format décimal ou exponentiel si la puissance est trop grande ou trop petite
s chaîne de caractères
Table 3.4 : Liste non exhaustive des codes utilisés pour formater des informations dans une chaîne de caractères
(voir page http:// docs.python.org/ library/ stdtypes.html ).
3. Types et variables du langage Python 38
3.2.5 T-uple
Un T-uple apparaît comme une liste d’objets comprise entre parenthèses et séparés par des virgules. Leur
création reprend le même format :
x = (4,5) # création d’un T-uple composé de 2 entiers
x = ("un",1,"deux",2) # création d’un T-uple composé de 2 chaînes de caractères
# et de 2 entiers, l’ordre d’écriture est important
x = (3,) # création d’un T-uple d’un élément, sans la virgule,
# le résultat est un entier
Ces objets sont des vecteurs d’objets. Il est possible d’effectuer les opérations regroupées dans la table 3.5.
Etant donné que les chaînes de caractères sont également des tableaux, ces opérations reprennent en partie
celles de la table 3.2.
x in s vrai si x est un des éléments de s
x not in s réciproque de la ligne précédente
s+t concaténation de s et t
s∗n concatène n copies de s les unes à la suite des autres
s[i] retourne le ième élément de s
s[i : j] retourne un T-uple contenant une copie des éléments de s d’indices i à j exclu.
retourne un T-uple contenant une copie des éléments de s dont les indices sont compris
s[i : j : k]
entre i et j exclu, ces indices sont espacés de k : i, i + k, i + 2k, i + 3k, ...
len(s) nombre d’éléments de s
plus petit élément de s, résultat difficile à prévoir lorsque les types des éléments sont diffé-
min(s)
rents
max(s) plus grand élément de s
sum(s) retourne la somme de tous les éléments
Table 3.5 : Opérations disponibles sur les T-uples, on suppose que s et t sont des T-uples, x est quant à lui
quelconque.
a = (4,5)
a [0] = 3 # déclenche une erreur d’exécution
Pour changer cet élément, il est possible de s’y prendre de la manière suivante :
a = (4,5)
a = (3,) + a[1:2] # crée un T-uple d’un élément concaténé
# avec la partie inchangée de a
3. Types et variables du langage Python 39
Le langage Python offre la possibilité de créer ses propres types immuables 5 mais ils seront définis à partir
des types immuables présentés jusqu’ici.
3.3.1 Liste
3.3.1.1 Définition et fonctions
Une liste apparaît comme une succession d’objets compris entre crochets et séparés par des virgules. Leur
création reprend le même format :
Ces objets sont des listes chaînées d’autres objets de type quelconque (immuable ou modifiable). Il est
possible d’effectuer les opérations regroupées dans la table 3.6. Ces opérations reprennent celles des T-uples
(voir table 3.5) et incluent d’autres fonctionnalités puisque les listes sont modifiables (voir table 3.6). Il
est donc possible d’insérer, de supprimer des éléments, de les trier. La syntaxe des opérations sur les listes
est similaire à celle des opérations qui s’appliquent sur les chaînes de caractères, elles sont présentées par
la table 3.7.
3.3.1.2 Exemples
Pour classer les objets contenus par la liste mais selon un ordre différent, il faut définir une fonction qui
détermine un ordre entre deux éléments de la liste. C’est la fonction compare de l’exemple suivant.
def compare (x,y): # crée une fonction
if x > y : return -1 # qui retourne -1 si x<y,
elif x == y : return 0 # 0 si x == y
else : return 1 # 1 si x < y
L’exemple suivant illustre un exemple dans lequel on essaye d’accéder à l’indice d’un élément qui n’existe
pas dans la liste :
x = [9,0,3,5,0]
print x.index (1) # cherche la position de l’élément 1
3. Types et variables du langage Python 41
Comme cet élément n’existe pas, on déclenche ce qu’on appelle une exception qui se traduit par l’affichage
d’un message d’erreur. Le message indique le nom de l’exception générée (ValueError) ainsi qu’un message
d’information permettant en règle générale de connaître l’événement qui en est la cause.
Traceback (most recent call last):
File "c:/temp/temp", line 2, in -toplevel-
print x.index(1)
ValueError: list.index(x): x not in list
Les listes sont souvent utilisées dans des boucles ou notamment par l’intermédiaire de la fonction range.
Cette fonction retourne une liste d’entiers.
Retourne une liste incluant tous les entiers compris entre debut et fin exclu. Si le paramètre facultatif
marche est renseigné, la liste contient tous les entiers n compris debut et fin exclu et tels que n − debut
soit un multiple de marche.
Exemple :
3. Types et variables du langage Python 42
La fonction xrange est d’un usage équivalent à range. Elle permet de parcourir une liste d’entiers sans la
créer vraiment. Elle est plus rapide.
print xrange (0,10,2) # affiche xrange(0,10,2)
Cette fonction est souvent utilisée lors de boucles 6 pour parcourir tous les éléments d’un T-uple, d’une
liste, d’un dictionnaire... Le programme suivant permet par exemple de calculer la somme de tous les
entiers impairs compris entre 1 et 20 exclu.
s = 0
for n in range (1,20,2) : # ce programme est équivalent à
s += n # s = sum (range(1,20,2))
Il est possible aussi de ne pas se servir des indices comme intermédiaires pour accéder aux éléments d’une
liste quand il s’agit d’effectuer un même traitement pour tous les éléments de la liste x.
x = ["un", 1, "deux", 2]
for el in x :
print "la liste inclut : ", el
L’instruction for el in x : se traduit littéralement par : pour tous les éléments de la liste, faire... Ce
programme a pour résultat :
la liste inclut : un
la liste inclut : 1
la liste inclut : deux
la liste inclut : 2
Il existe également des notations abrégées lorsqu’on cherche à construire une liste à partir d’une autre.
Le programme suivant construit la liste des entiers de 1 à 5 à partir du résultat retourné par la fonction
range.
y = list ()
for i in range(0,5) : y.append (i+1)
print y # affiche [1,2,3,4,5]
Le langage Python offre la possibilité de résumer cette écriture en une seule ligne. Cette syntaxe sera
reprise au paragraphe 4.3.2.2.
y = [ i+1 for i in range (0,5)]
print y # affiche [1,2,3,4,5]
Cette définition de liste peut également inclure des tests ou des boucles imbriquées.
y = [ i for i in range(0,5) if i % 2 == 0] # sélection les éléments pairs
print y # affiche [0,2,4]
z = [ i+j for i in range(0,5) \
for j in range(0,5)] # construit tous les nombres i+j possibles
print z # affiche [0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 2,
# 3, 4, 5, 6, 3, 4, 5, 6, 7, 4, 5, 6, 7, 8]
On suppose qu’on dispose de n séquences d’éléments (T-uple, liste), toutes de longueur l. La fonction zip
permet de construire une liste de T-uples qui est la juxtaposition de toutes ces séquences. Le iième T-uple
de la liste résultante contiendra tous les iième éléments des séquences juxtaposées. Si les longueurs des
séquences sont différentes, la liste résultante aura même taille que la plus courte des séquences.
a = (1,0,7,0,0,0)
b = [2,2,3,5,5,5]
c = [ "un", "deux", "trois", "quatre" ]
d = zip (a,b,c)
print d # affiche [(1, 2, ’un’), (0, 2, ’deux’),
# (7, 3, ’trois’), (0, 5, ’quatre’)]
Il arrive fréquemment de constuire une chaîne de caractères petits bouts par petits bouts comme le montre
le premier exemple ci-dessous. Cette construction peut s’avérer très lente lorsque le résultat est long. Dans
ce cas, il est nettement plus rapide d’ajouter chaque morceau dans une liste puis de les concaténer en une
seule fois grâce à la méthode join.
s = "" s = []
while <condition> : s += ... while <condition> : s.append ( ... )
s = "".join (s)
3.3.2 Copie
A l’inverse des objets de type immuable, une affectation ne signifie pas une copie. Afin d’éviter certaines
opérations superflues et parfois coûteuses en temps de traitement, on doit distinguer la variable de son
contenu. Une variable désigne une liste avec un mot (ou identificateur), une affection permet de créer un
second mot pour désigner la même liste. Il est alors équivalent de faire des opérations avec le premier mot
ou le second comme le montre l’exemple suivant avec les listes l et l2.
l = [4,5,6]
l2 = l
print l # affiche [4,5,6]
print l2 # affiche [4,5,6]
l2 [1] = "modif"
print l # affiche [4, ’modif’, 6]
print l2 # affiche [4, ’modif’, 6]
Dans cet exemple, il n’est pas utile de créer une seconde variable, dans le suivant, cela permet quelques
raccourcis.
l = [[0,1], [2,3]]
l1 = l [0]
l1 [0] = "modif" # ligne équivalente à : l [0][0] = "modif"
Par conséquent, lorsqu’on affecte une liste à une variable, celle-ci n’est pas recopiée, la liste reçoit seulement
un nom de variable. L’affectation est en fait l’association d’un nom avec un objet (voir paragraphe 5.6).
Pour copier une liste, il faut utiliser la fonction copy du module copy 7 . Ce point sera rappelé au para-
graphe 5.6.3 (page 101).
import copy
l = [4,5,6]
l2 = copy.copy(l)
7. Le module copy est une extension interne. C’est une librairie de fonctions dont la fonction copy. Cette syntaxe sera
vue au chapitre 7.
3. Types et variables du langage Python 44
L’opérateur == permet de savoir si deux listes sont égales même si l’une est une copie de l’autre. Le
mot-clé is permet de vérifier si deux variables font référence à la même liste ou si l’une est une copie de
l’autre comme le montre l’exemple suivant :
import copy
l = [1,2,3]
l2 = copy.copy (l)
l3 = l
La fonction deepcopy est plus lente à exécuter car elle prend en compte les références récursives comme
celles de l’exemple suivant où deux listes se contiennent l’une l’autre.
l = [1,"a"]
ll = [l,3] # ll contient l
l [0] = ll # l contient ll
print l # affiche [[[...], 3], ’a’]
print ll # affiche [[[...], ’a’], 3]
import copy
z = copy.deepcopy (l)
print z # affiche [[[...], 3], ’a’]
3.3.3 Dictionnaire
Les dictionnaires sont des tableaux plus souples que les listes. Une liste référence les éléments en leur
donnant une position : la liste associe à chaque élément une position entière comprise entre 0 et n − 1
si n est la longueur de la liste. Un dictionnaire permet d’associer à un élément autre chose qu’une position
entière : ce peut être un entier, un réel, une chaîne de caractères, un T-uple contenant des objets immuables.
D’une manière générale, un dictionnaire associe à une valeur ce qu’on appelle une clé de type immuable.
Cette clé permettra de retrouver la valeur associée.
L’avantage principal des dictionnaires est la recherche optimisée des clés. Par exemple, on recense les
noms des employés d’une entreprise dans une liste. On souhaite ensuite savoir si une personne ayant un
nom précisé à l’avance appartient à cette liste. Il faudra alors parcourir la liste jusqu’à trouver ce nom ou
3. Types et variables du langage Python 45
parcourir toute la liste si jamais celui-ci ne s’y trouve pas 8 . Dans le cas d’un dictionnaire, cette recherche
du nom sera beaucoup plus rapide à écrire et à exécuter.
Un dictionnaire apparaît comme une succession de couples d’objets comprise entre accolades et séparés
par des virgules. La clé et sa valeur sont séparées par le symbole :. Leur création reprend le même format :
x = { "cle1":"valeur1", "cle2":"valeur2" }
y = { } # crée un dictionnaire vide
z = dict () # crée aussi un dictionnaire vide
Les indices ne sont plus entiers mais des chaînes de caractères pour cet exemple. Pour associer la valeur à
la clé "cle1", il suffit d’écrire :
print x ["cle1"]
La plupart des fonctions disponibles pour les listes sont interdites pour les dictionnaires comme la conca-
ténation ou l’opération de multiplication (∗). Il n’existe plus non plus d’indices entiers pour repérer les
éléments, le seul repère est leur clé. La table 3.8 dresse la liste des opérations simples sur les dictionnaires
tandis que la table 3.9 dresse la liste des méthodes plus complexes.
Contrairement à une liste, un dictionnaire ne peut être trié car sa structure interne est optimisée pour
effectuer des recherches rapides parmi les éléments. On peut aussi se demander quel est l’intérêt de la
méthode popitem qui retourne un élément puis le supprime alors qu’il existe le mot-clé del. Cette méthode
est simplement plus rapide car elle choisit à chaque fois l’élément le moins coûteux à supprimer, surtout
lorsque le dictionnaire est volumineux.
Les itérateurs sont des objets qui permettent de parcourir rapidement un dictionnaire, ils seront décrits en
détail au chapitre 5 sur les classes. Un exemple de leur utilisation est présenté dans le paragraphe suivant.
3.3.3.2 Exemples
Il n’est pas possible de trier un dictionnaire. L’exemple suivant permet néanmoins d’afficher tous les
éléments d’un dictionnaire selon un ordre croissant des clés. Ces exemples font appel aux paragraphes sur
8. voir également le paragraphe 4.7.1, page 76
3. Types et variables du langage Python 46
L’exemple suivant montre un exemple d’utilisation des itérateurs. Il s’agit de construire un dictionnaire
inversé pour lequel les valeurs seront les clés et réciproquement.
d = { "un":1, "zero":0, "deux":2, "trois":3, "quatre":4, "cinq":5, \
"six":6, "sept":1, "huit":8, "neuf":9, "dix":10 }
Pour être plus efficace, on peut remplacer la ligne for key, value in d.items() : par : for key, value in d.iteritems() :.
De cette manière, on parcourt les éléments du dictionnaire sans créer de liste intermédiaire. Il est équi-
valent d’utiliser l’une ou l’autre au sein d’une boucle même si le programme suivant montre une différence.
Il a pour résultat :
[(’trois’, 3), (’sept’, 1), (’neuf’, 9), (’six’, 6), (’zero’, 0),
(’un’, 1), (’dix’, 10), (’deux’, 2), (’huit’, 8), (’quatre’, 4),
(’cinq’, 5)]
3.3.3.3 Copie
A l’instar des listes (voir paragraphe 3.3.2), les dictionnaires sont des objets et une affectation n’est pas
équivalente à une copie comme le montre le programme suivant.
d = {4:4,5:5,6:6}
d2 = d
print d # affiche {4: 4, 5: 5, 6: 6}
print d2 # affiche {4: 4, 5: 5, 6: 6}
d2 [5] = "modif"
print d # affiche {4: 4, 5: ’modif’, 6: 6}
print d2 # affiche {4: 4, 5: ’modif’, 6: 6}
Lorsqu’on affecte une liste à une variable, celle-ci n’est pas recopiée, la liste reçoit seulement un nom de
variable. L’affectation est en fait l’association d’un nom avec un objet (voir paragraphe 5.6). Pour copier
une liste, il faut utiliser la fonction copy du module copy.
d = {4:4,5:5,6:6}
import copy
d2 = copy.copy(l)
print d # affiche {4: 4, 5: 5, 6: 6}
print d2 # affiche {4: 4, 5: 5, 6: 6}
d2 [5] = "modif"
print d # affiche {4: 4, 5: 5, 6: 6}
print d2 # affiche {4: 4, 5: ’modif’, 6: 6}
Le mot-clé is a la même signification pour les dictionnaires que pour les listes, l’exemple du para-
graphe 3.3.2 (page 43) est aussi valable pour les dictionnaires. Il en est de même pour la remarque
concernant la fonction deepcopy. Cette fonction recopie les listes et les dictionnaires.
Ce paragraphe concerne davantage des utilisateurs avertis qui souhaitent malgré tout utiliser des clés de
type modifiable. Dans l’exemple qui suit, la clé d’un dictionnaire est également un dictionnaire et cela
provoque une erreur. Il en serait de même si la variable k utilisée comme clé était une liste.
k = { 1:1}
Traceback (most recent call last):
d = { }
File "cledict.py", line 3, in <module>
d [k] = 0
d [k] = 0
TypeError: dict objects are unhashable
Cela ne veut pas dire qu’il faille renoncer à utiliser un dictionnaire ou une liste comme clé. La fonction id
permet d’obtenir un entier qui identifie de manière unique tout objet. Le code suivant est parfaitement
correct.
k = { 1:1}
d = { }
d [id (k)] = 0
3. Types et variables du langage Python 48
Toutefois, ce n’est pas parce que deux dictionnaires auront des contenus identiques que leurs identifiants
retournés par la fonction id seront égaux. C’est ce qui explique l’erreur que provoque la dernière ligne du
programme suivant.
k = {1:1}
d = { }
d [id (k)] = 0
b = k
print d [id(b)] # affiche bien zéro
c = {1:1}
print d [id(c)] # provoque une erreur car même si k et c ont des contenus égaux,
# ils sont distincts, la clé id(c) n’existe pas dans d
Il existe un cas où on peut se passer de la fonction id mais il inclut la notion de classe définie au chapitre 5.
L’exemple suivant utilise directement l’instance k comme clé. En affichant le dictionnaire d, on vérifie que
la clé est liée au résultat de l’instruction id(k) même si ce n’est pas la clé.
class A : pass
k = A ()
d = { }
d [k] = 0
print d # affiche {<__main__.A object at 0x0120DB90>: 0}
print id (k), hex(id(k)) # affiche 18930576, 0x120db90
print d [id(k)] # provoque une erreur
La fonction hex convertit un entier en notation hexadécimale. Les nombres affichés changent à chaque
exécution. Pour conclure, ce dernier exemple montre comment se passer de la fonction id dans le cas d’une
clé de type dictionnaire.
class A (dict):
def __hash__(self):
return id(self)
k = A ()
k ["t"]= 4
d = { }
d [k] = 0
print d # affiche {{’t’: 4}: 0}
3.4 Extensions
3.4.1 Mot-clé print, repr, conversion en chaîne de caractères
Le mot-clé print est déjà apparu dans les exemples présentés ci-dessus, il permet d’afficher une ou plusieurs
variables préalablement définies, séparées par des virgules. Les paragraphes qui suivent donnent quelques
exemples d’utilisation. La fonction print permet d’afficher n’importe quelle variable ou objet à l’écran,
cet affichage suppose la conversion de cette variable ou objet en une chaîne de caractères. Deux fonctions
permettent d’effectuer cette étape sans toutefois afficher le résultat à l’écran.
La fonction str (voir paragraphe 3.2.4.2) permet de convertir toute variable en chaîne de caractères. Il
existe cependant une autre fonction repr, qui effectue cette conversion. Dans ce cas, le résultat peut être
interprété par la fonction eval (voir paragraphe 3.4.2) qui se charge de la conversion inverse. Pour les types
simples comme ceux présentés dans ce chapitre, ces deux fonctions retournent des résultats identiques.
Pour l’exemple, x désigne n’importe quelle variable.
x == eval (repr(x)) # est toujours vrai (True)
x == eval (str (x)) # n’est pas toujours vrai
3. Types et variables du langage Python 49
Le programme va créer une chaîne de caractères pour chacune des opérations et celle-ci sera évaluée
grâce à la fonction eval comme si c’était une expression numérique. Il faut bien sûr que les variables que
l’expression mentionne existent durant son évaluation.
Certaines variables - des chaînes des caractères - existent déjà avant même la première instruction. Elles
contiennent différentes informations concernant l’environnement dans lequel est exécuté le programme
Python :
Ce module contient tous les éléments présents dès le début d’un programme Python,
__builtins__ il contient entre autres les types présentés dans ce chapitre et des fonctions simples
comme range.
C’est une chaîne commentant le fichier, c’est une chaîne de caractères insérée aux
__doc__
premières lignes du fichiers et souvent entourée des symboles ””” (voir chapitre 7).
__file__ Contient le nom du fichier où est écrit ce programme.
__name__ Contient le nom du module.
La fonction dir est également pratique pour afficher toutes les fonctions d’un module. L’instruction
dir(sys) affiche la liste des fonctions du module sys (voir chapitre 7).
3. Types et variables du langage Python 50
Cette particularité reviendra lorsque les fonctions seront décrites puisqu’il est possible qu’une fonction
retourne plusieurs résultats comme la fonction divmod illustrée par le programme suivant.
x,y = divmod (17,5)
print x,y # affiche 3 2
print "17 / 5 = 5 * ", x, " + ",y # affiche 17 / 5 = 5 * 3 + 2
Le langage Python offre la possibilité d’effectuer plusieurs affectations sur la même ligne. Dans l’exemple
qui suit, le couple (5, 5) est affecté à la variable point, puis le couple x, y reçoit les deux valeurs du T-uple
point.
x,y = point = 5,5
3.4.6 Ensemble
Le langage Python définit également ce qu’on appelle un ensemble. Il est défini par les classes set de type
modifiable et la classe frozenset de type immuable. Ils n’acceptent que des types identiques et offrent la
plupart des opérations liées aux ensembles comme l’intersection, l’union. D’un usage moins fréquent, ils
ne seront pas plus détaillés 10 .
print set ( (1,2,3) ) & set ( (2,3,5) )
# construit l’intersection qui est set([2, 3])
Ce chapitre a présenté les différents types de variables définis par le langage Python pour manipuler des
données ainsi que les opérations possibles avec ces types de données. Le chapitre suivant va présenter les
tests, les boucles et les fonctions qui permettent de réaliser la plupart des programmes informatiques.
9. La différence dépend des opérations effectuées.
10. La page http://docs.python.org/library/stdtypes.html#set décrit l’ensemble des fonctionnalités qui leur sont attachées.
Chapitre 4
Syntaxe du langage Python (boucles, tests,
fonctions)
Avec les variables, les boucles et les fonctions, on connaît suffisamment d’éléments pour écrire des pro-
grammes. Le plus difficile n’est pas forcément de les comprendre mais plutôt d’arriver à découper un
algorithme complexe en utilisant ces briques élémentaires. C’est l’objectif des chapitres centrés autour des
exercices. Toutefois, même si ce chapitre présente les composants élémentaires du langage, l’aisance qu’on
peut acquérir en programmation vient à la fois de la connaissance du langage mais aussi de la connaissance
d’algorithmes standards comme celui du tri ou d’une recherche dichotomique. C’est cette connaissance tout
autant que la maîtrise d’un langage de programmation qui constitue l’expérience en programmation.
Tout programme peut se résumer à ces trois concepts. Chaque langage les met en place avec sa propre
syntaxe et parfois quelques nuances mais il est souvent facile de les reconnaître même dans des langages
inconnus. Le calcul d’une somme décrit plus haut et écrit en Python correspond à l’exemple suivant :
moy = 0
for i in range(1,N+1): # de 1 à N+1 exclu --> de 1 à N inclus
moy += n [i]
moy /= N
4. Syntaxe du langage Python (boucles, tests, fonctions) 52
Le premier élément de cette syntaxe est constitué de ses mots-clés (for et in) (voir également table 4.1)
et des symboles (=, +=, /=, [, ], (, ), :) (voir table 4.2) La fonction iskeyword du module keyword 1 permet
de savoir si un mot-clé donné fait partie du langage Python.
import keyword
print keyword.iskeyword("for") # affiche True
print keyword.iskeyword("until") # affiche False
4.2 Tests
4.2.1 Définition et syntaxe
La clause else est facultative. Lorsque la condition condition1 est fausse et qu’il n’y a aucune
instruction à exécuter dans ce cas, la clause else est inutile. La syntaxe du test devient :
if condition1 :
instruction1
instruction2
...
S’il est nécessaire d’enchaîner plusieurs tests d’affilée, il est possible de condenser l’écriture avec le
mot-clé elif :
if condition1 :
instruction1
instruction2
...
elif condition2 :
instruction3
instruction4
...
elif condition3 :
instruction5
instruction6
...
else :
instruction7
instruction8
...
Une ligne est mal indentée (print "le nombre est négatif"). Elle ne devrait être exécutée que si la
condition x > 0 n’est pas vérifiée. Le fait qu’elle soit alignée avec les premières instructions du programme
fait que son exécution n’a plus rien à voir avec cette condition. La programme répond de manière erronée :
4. Syntaxe du langage Python (boucles, tests, fonctions) 54
Dans certains cas, l’interpréteur Python ne sait pas à quel bloc attacher une instruction, c’est le cas de
l’exemple suivant, la même ligne a été décalée de deux espaces, ce qui est différent de la ligne qui précède
et de la ligne qui suit.
x = 1
if x > 0 :
signe = 1
print "le nombre est positif"
else :
signe = -1
print "le nombre est négatif" # ligne mal indentée
print "signe = ", signe
Le second cas d’écriture condensée concerne les comparaisons enchaînées. Le test if 3 < x and x < 5 : instruction
peut être condensé par if 3 < x < 5 : instruction. Il est ainsi possible de juxtaposer autant de comparai-
sons que nécessaire : if 3 < x < y < 5 : instruction.
Le mot-clé in permet également de condenser certains tests lorsque la variable à tester est entière.
if x == 1 or x == 6 or x == 50 : peut être résumé simplement par if x in (1, 6, 50) :.
4.2.5 Exemple
L’exemple suivant associe à la variable signe le signe de la variable x.
x = -5 x = -5
if x < 0 : if x < 0 : signe = -1
signe = -1 Son écriture condensée elif x == 0 : signe = 0
elif x == 0 : lorsqu’il n’y a qu’une else : signe = 1
signe = 0
else : instruction à exécuter :
signe = 1
Le programme suivant saisit une ligne au clavier et dit si c’est "oui" ou "non" qui a été saisi.
s = raw_input ("dites oui : ") # voir remarque suivante
if s == "oui" or s [0:1] == "o" or s [0:1] == "O" or s == "1" :
print "oui"
else : print "non"
import Tkinter
def question (legende) :
reponse = [""]
root = Tkinter.Tk ()
root.title ("pseudo raw_input") 5
Tkinter.Label (text = legende).pack (side = Tkinter.LEFT)
s = Tkinter.Entry (text= "def", width=80)
s.pack (side = Tkinter.LEFT)
def rget () :
reponse [0] = s.get () 10
root.destroy ()
Tkinter.Button (text = "ok", command = rget).pack (side = Tkinter.LEFT)
root.mainloop ()
return reponse [0]
15
print "reponse ", question ("texte de la question")
Figure 4.1 : Fenêtre apparaissant lors de l’exécution du programme page 55 proposant une version graphique de la
fonction raw_input.
4. Syntaxe du langage Python (boucles, tests, fonctions) 56
Dans ce cas précis, si l’instruction pass est oubliée, l’interpréteur Python génère l’erreur suivante :
File "nopass.py", line 6
else :
^
IndentationError: expected an indented block
4.3 Boucles
Le langage Python propose deux types de boucles. La boucle while suit scrupuleusement la définition 4.8.
La boucle for est une boucle while déguisée (voir paragraphe 4.3.2), elle propose une écriture simplifiée
pour répéter la même séquence d’instructions pour tous les éléments d’un ensemble.
4. Syntaxe du langage Python (boucles, tests, fonctions) 57
Où cond est une condition qui détermine la poursuite de la répétition des instructions incluses dans
la boucle. Tant que celle-ci est vraie, les instructions 1 à n sont exécutées.
Tout comme les tests, la remarque 4.4 concernant l’indentation reste vraie. Le décalage des lignes d’un
cran vers la droite par rapport à l’instruction while permet de les inclure dans la boucle comme le montre
l’exemple suivant.
n = 0 à l’intérieur 0
while n < 3: à l’intérieur 1
print "à l’intérieur ", n Résultat : à l’intérieur 2
n += 1 à l’extérieur 3
print "à l’extérieur ", n
4.3.1.2 Condition
Les conditions suivent la même syntaxe que celles définies lors des tests (voir paragraphes 4.2.2 et 4.2.3).
A moins d’inclure l’instruction break 2 qui permet de sortir prématurément d’une boucle, la condition
qui régit cette boucle doit nécessairement être modifiée à l’intérieur de celle-ci. Dans le cas contraire, on
appelle une telle boucle une boucle infinie puisqu’il est impossible d’en sortir. L’exemple suivant contient
une boucle infinie car le symbole = est manquant dans la dernière instruction. La variable n n’est jamais
modifiée et la condition n < 3 toujours vraie.
n = 0
while n < 3 :
print n
n + 1 # n n’est jamais modifié, l’instruction correcte serait n += 1
Où x est un élément de l’ensemble set. Les instructions 1 à n sont exécutées pour chaque élément x de
l’ensemble set. Cet ensemble peut être une chaîne de caractères, un T-uple, une liste, un dictionnaire
ou tout autre type incluant des itérateurs qui sont présentés au chapitre 5 concernant les classes
(page 91).
Tout comme les tests, la remarque 4.4 concernant l’indentation reste vraie. L’exemple suivant affiche tous
les éléments d’un T-uple à l’aide d’une boucle for.
t = (1,2,3,4)
for x in t: # affiche les nombres 1,2,3,4
print x # chacun sur une ligne différente
Lors de l’affichage d’un dictionnaire, les éléments n’apparaissent pas triés ni dans l’ordre dans lequel ils
y ont été insérés. L’exemple suivant montre comment afficher les clés et valeurs d’un dictionnaire dans
l’ordre croissant des clés.
d = { 1:2, 3:4, 5:6, 7:-1, 8:-2 }
print d # affiche le dictionnaire {8: -2, 1: 2, 3: 4, 5: 6, 7: -1}
k = d.keys ()
print k # affiche les clés [8, 1, 3, 5, 7]
k.sort ()
print k # affiche les clés triées [1, 3, 5, 7, 8]
for x in k: # affiche les éléments du dictionnaire
print x,":",d [x] # triés par clés croissantes
Le langage Python propose néanmoins la fonction sorted qui réduit l’exemple suivant en trois lignes :
d = { 1:2, 3:4, 5:6, 7:-1, 8:-2 }
for x in sorted(d): # pour les clés dans l’ordre croissant
print x,":",d [x]
La boucle la plus répandue est celle qui parcourt des indices entiers compris entre 0 et n − 1. On utilise
pour cela la boucle for et la fonction range ou xrange comme dans l’exemple qui suit. La différence entre
ces deux fonctions a déjà été présentée au paragraphe 3.3.1.3 (page 41).
sum = 0
N = 10
for n in range(0,N): # ou for n in xrange(0,N): (plus rapide)
sum += n # additionne tous les entiers compris entre 0 et N-1
Le paragraphe 3.3.1.4 a montré comment le mot-clé for peut être utilisé pour simplifier la création d’une
liste à partir d’une autre. La syntaxe suit le schéma suivant :
Où expression est une expression numérique incluant ou non x, la variable de la boucle, ensemble
est un ensemble d’éléments, T-uple, liste, dictionnaire.
Cette syntaxe permet de résumer en une ligne la création de la séquence y du programme suivant.
y = list ()
for i in range(0,5) :
y.append (i+1)
print y # affiche [1,2,3,4,5]
Un autre exemple de cette syntaxe réduite a été présenté au paragraphe 3.3.1.4 page 42. Cette écriture
condensée est bien souvent plus lisible même si tout dépend des préférences de celui qui programme.
4. Syntaxe du langage Python (boucles, tests, fonctions) 59
4.3.2.3 Itérateurs
Toute boucle for peut s’appliquer sur un objet muni d’un itérateur tels que les chaînes de caractères,
T-uples, les listes, les dictionnaires.
d = ["un", "deux", "trois"]
for x in d:
print x # affichage de tous les éléments de d
Cette syntaxe réduite a déjà été introduite pour les listes et les dictionnaires au chapitre précédent. Il existe
une version équivalente avec la boucle while utilisant de façon explicite les itérateurs. Il peut être utile de
lire le chapitre suivant sur les classes et le chapitre 6 sur les exceptions avant de revenir sur la suite de cette
section qui n’est de toutes façons pas essentielle. L’exemple précédent est convertible en une boucle while
en faisant apparaître explicitement les itérateurs (voir paragraphe 5.4.2). Un itérateur est un objet qui
permet de parcourir aisément un ensemble. La fonction it = iter(e) permet d’obtenir un itérateur it sur
l’ensemble e. L’appel à l’instruction it.next() parcourt du premier élément jusqu’au dernier en retournant
la valeur de chacun d’entre eux. Lorsqu’il n’existe plus d’élément, l’exception StopIteration est déclenchée
(voir paragraphe 6). Il suffit de l’intercepter pour mettre fin au parcours.
d = ["un", "deux", "trois"]
it = iter (d) # obtient un itérateur sur d
while True:
try: x = it.next () # obtient l’élément suivant, s’il n’existe pas
except StopIteration: break # déclenche une exception
print x # affichage de tous les éléments de d
Jusqu’à présent, la boucle for n’a été utilisée qu’avec une seule variable de boucle, comme dans l’exemple
suivant où on parcourt une liste de T-uple pour les afficher.
d = [ (1,0,0), (0,1,0), (0,0,1) ]
for v in d: print v
Lorsque les éléments d’un ensemble sont des T-uples, des listes ou des dictionnaires composés de taille
fixe, il est possible d’utiliser une notation qui rappelle les affectations multiples (voir paragraphe 3.4.4).
L’exemple précédent devient dans ce cas :
d = [ (1,0,0), (0,1,0), (0,0,1) ]
for x,y,z in d: print x,y,z
Cette écriture n’est valable que parce que chaque élément de la liste d est un T-uple composé de trois
nombres. Lorsqu’un des éléments est de taille différente à celle des autres, comme dans l’exemple suivant,
une erreur survient.
d = [ (1,0,0), (0,1,0,6), (0,0,1) ] # un élément de taille quatre
for x,y,z in d: print x,y,z
Cette syntaxe est très pratique associée à la fonction zip (voir paragraphe 3.3.1.5). Il est alors possible de
parcourir plusieurs séquences (T-uple, liste, dictionnaire) simultanément.
a = range(0,5) 0 est le carré de 0
b = [x**2 for x in a] 1 est le carré de 1
for x,y in zip (a,b): 4 est le carré de 2
print y, " est le carré de ", x 9 est le carré de 3
# affichage à droite 16 est le carré de 4
4. Syntaxe du langage Python (boucles, tests, fonctions) 60
Il existe peu de cas où la boucle while s’écrit sur une ligne car elle inclut nécessairement une instruction
permettant de modifier la condition d’arrêt.
d = ["un", "deux", "trois"]
i = 0
while d [i] != "trois" : i += 1
print "trois a pour position ", i
Pour certains éléments d’une boucle, lorsqu’il n’est pas nécessaire d’exécuter toutes les instructions, il est
possible de passer directement à l’élément suivant ou l’itération suivante. Le programme suivant utilise la
crible d’Eratosthène 3 pour dénicher tous les nombres premiers compris entre 1 et 99.
d = dict ()
for i in range(1,100): # d [i] est vrai si i est un nombre premier
d [i] = True # au début, comme on ne sait pas, on suppose
# que tous les nombres sont premiers
for i in range(2,100):
# si d [i] est faux,
if not d [i]: continue # les multiples de i ont déjà été cochés
# et peut passer à l’entier suivant
for j in range (2,100):
if i*j < 100:
d [i*j] = False # d [i*j] est faux pour tous les multiples de i
# inférieurs à 100
print "liste des nombres premiers"
for i in d:
if d [i]: print i
for i in range(2,100):
if d [i]:
for j in range (2,100):
if i*j < 100 :
d [i*j] = False
Le mot-clé continue évite de trop nombreuses indentations et rend les programmes plus lisibles.
3. Le crible d’Eratosthène est un algorithme permettant de déterminer les nombres premiers. Pour un nombre premier p,
il paraît plus simple de considérer tous les entiers de p − 1 à 1 pour savoir si l’un d’eux divise p. C’est ce qu’on fait lorsqu’on
doit vérifier le caractère premier d’un seul nombre. Pour plusieurs nombres à la fois, le crible d’Eratosthène est plus efficace :
au lieu de s’intéresser aux diviseurs, on s’intéresse aux multiples d’un nombre. Pour un nombre i, on sait que 2i, 3i, ... ne
sont pas premiers. On les raye de la liste. On continue avec i + 1, 2(i + 1), 3(i + 1)...
4. Syntaxe du langage Python (boucles, tests, fonctions) 61
Lors de l’écriture d’une boucle while, il n’est pas toujours adéquat de résumer en une seule condition
toutes les raisons pour lesquelles il est nécessaire d’arrêter l’exécution de cette boucle. De même, pour une
boucle for, il n’est pas toujours utile de visiter tous les éléments de l’ensemble à parcourir. C’est le cas
par exemple lorsqu’on recherche un élément, une fois qu’il a été trouvé, il n’est pas nécessaire d’aller plus
loin. L’instruction break permet de quitter l’exécution d’une boucle.
l = [6,7,5,4,3]
n = 0
c = 5
for x in l:
if x == c: break# l’élément a été trouvé, on sort de la boucle
n += 1 # si l’élément a été trouvé, cette instruction
# n’est pas exécutée
print "l’élément ",c, " est en position ",
print n # affiche l’élément 5 est en position 2
Si deux boucles sont imbriquées, l’instruction break ne sort que de la boucle dans laquelle elle est insérée.
L’exemple suivant vérifie si un entier est la somme des carrés de deux entiers compris entre 1 et 20.
set = range (1,21)
n = 53
for x in set:
for y in set:
c = x*x + y*y
if c == n: break
if c == n: break # cette seconde instruction break est nécessaire
# pour sortir de la seconde boucle
# lorsque la solution a été trouvée
if c == n:
# le symbole \ permet de passer à la ligne sans changer d’instruction
print n, " est la somme des carrés de deux entiers :", \
x, "*", x, "+", y, "*", y, "=", n
else:
print n, " n’est pas la somme des carrés de deux entiers"
Le programme affiche :
53 est la somme des carrés de deux entiers : 2 * 2 + 7 * 7 = 53
Le mot-clé else existe aussi pour les boucles et s’utilise en association avec le mot-clé break. L’instruction
else est placée à la fin d’une boucle, indentée au même niveau que for ou while. Les lignes qui suivent
le mot-clé else ne sont exécutées que si aucune instruction break n’a été rencontrée dans le corps de la
boucle. On reprend l’exemple du paragraphe précédent. On recherche cette fois-ci la valeur 1 qui ne se
trouve pas dans la liste L. Les lignes suivant le test if x == c ne seront jamais exécutées au contraire de
la dernière.
L = [6,7,5,4,3]
n = 0
c = 1
for x in L :
if x == c :
print "l’élément ", c, " est en position ", n
break
n += 1
else:
print "aucun élément ", c, " trouvé" # affiche aucun élément 1 trouvé
Les lignes dépendant de la clause else seront exécutées dans tous les cas où l’exécution de la boucle n’est
pas interrompue par une instruction break ou une instruction return 4 ou par la levée d’une exception 5 .
4. voir les fonctions au paragraphe 4.4
5. voir paragraphe 6
4. Syntaxe du langage Python (boucles, tests, fonctions) 62
En parcourant la liste en se servant des indices, il est possible de supprimer une partie de cette liste. Il
faut néanmoins faire attention à ce que le code ne produise pas d’erreur comme c’est le cas pour le suivant.
La boucle for parcourt la liste range(0, len(li)) qui n’est pas modifiée en même temps que l’instruction
del li[i : i + 2].
li = range (0,10)
print li # affiche [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for i in range (0, len (li)):
if i == 5 :
del li [i:i+2]
print li [i] # affiche successivement 0, 1, 2, 3, 4, 7, 8, 9 et
# produit une erreur
print li
Le programme suivant marche parfaitement puisque cette fois-ci la boucle parcourt la liste li. En revanche,
pour la suppression d’une partie de celle-ci, il est nécessaire de conserver en mémoire l’indice de l’élément
visité. C’est le rôle de la variable i.
li = range (0,10)
print li # affiche [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
i = 0
for t in li :
if i == 5 : del li [i:i+2]
i = i+1
print t # affiche successivement 0, 1, 2, 3, 4, 5, 8, 9
print li # affiche [0, 1, 2, 3, 4, 7, 8, 9]
Le langage Python offre la possibilité de supprimer des éléments d’une liste alors même qu’on est en train
de la parcourir. Le programme qui suit ne marche pas puisque l’instruction del i ne supprime pas un
élément de la liste mais l’identificateur i qui prendra une nouvelle valeur lors du passage suivant dans la
boucle.
li = range (0,10)
print li # affiche [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for i in li :
if i == 5 : del i
print li # affiche [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
On pourrait construire des exemples similaires dans le cadre de l’ajout d’un élément à la liste. Il est en
règle générale déconseillé de modifier une liste, un dictionnaire pendant qu’on le parcourt. Malgré tout, si
cela s’avérait indispensable, il convient de faire plus attention dans ce genre de situations.
4.4 Fonctions
Les fonctions sont des petits programmes qui effectuent des tâches plus précises que le programme entier.
On peut effectivement écrire un programme sans fonction mais ils sont en général illisibles. Utiliser des
fonctions implique de découper un algorithme en tâches élémentaires. Le programme final est ainsi plus
facile à comprendre. Un autre avantage est de pouvoir plus facilement isoler une erreur s’il s’en produit
une : il suffit de tester une à une les fonctions pour déterminer laquelle retourne un mauvais résultat.
L’avantage le plus important intervient lorsqu’on doit effectuer la même chose à deux endroits différentes
d’un programme : une seule fonction suffit et elle sera appelée à ces deux endroits 6 .
6. Pour les utilisateurs experts : en langage Python, les fonctions sont également des variables, elles ont un identificateur
et une valeur qui est dans ce cas un morceau de code. Cette précision explique certaines syntaxes du chapitre 9 sur les
interfaces graphiques ou celle introduite en fin de chapitre au paragraphe 4.7.10.
4. Syntaxe du langage Python (boucles, tests, fonctions) 63
Lorsqu’on écrit ses premiers programme, on écrit souvent des fonctions plutôt longues avant de s’apercevoir
que certains parties sont identiques ailleurs. On extrait donc la partie répétée pour en faire une fonction.
Avec l’habitude, on finit par écrire des fonctions plus petites et réutilisables.
fonction_nom est le nom de la fonction, il suit les mêmes règles que le nom des variables. par_1 à
par_n sont les noms des paramètres et res_1 à res_n sont les résultats retournés par la fonction.
Les instructions associées à une fonction doivent être indentées par rapport au mot-clé def.
S’il n’y a aucun résultat, l’instruction return est facultative ou peut être utilisée seule sans être suivie par
une valeur ou une variable. Cette instruction peut apparaître plusieurs fois dans le code de la fonction
mais une seule d’entre elles sera exécutée. A partir de ce moment, toute autre instruction de la fonction
sera ignorée. Pour exécuter une fonction ainsi définie, il suffit de suivre la syntaxe suivante :
Où fonction_nom est le nom de la fonction, valeur_1 à valeur_n sont les noms des paramètres,
x_1 à x_n reçoivent les résultats retournés par la fonction. Cette affectation est facultative. Si on
ne souhaite pas conserver les résultats, on peut donc appeler la fonction comme suit :
fonction_nom (valeur_1, valeur_2, ..., valeur_n)
Lorsqu’on commence à programmer, il arrive parfois qu’on confonde le rôle des mots-clés print et return.
Dans ce cas, il faut se reporter à la remarque 11.3 page 222.
4.4.2 Exemple
Le programme suivant utilise deux fonctions. La première convertit des coordonnées cartésiennes en coor-
données polaires. Elle prend deux réels en paramètres et retourne deux autres réels. La seconde fonction
affiche les résultats de la première pour tout couple de valeurs (x, y). Elle ne retourne aucun résultat.
import math
def coordonnees_polaires (x,y):
rho = math.sqrt(x*x+y*y) # calcul la racine carrée de x*x+y*y
theta = math.atan2 (y,x) # calcule l’arc tangente de y/x en tenant
# compte des signes de x et y
return rho, theta
affichage (1,1)
affichage (0.5,1)
4. Syntaxe du langage Python (boucles, tests, fonctions) 64
affichage (-0.5,1)
affichage (-0.5,-1)
affichage (0.5,-1)
Où fonction_nom est le nom de la fonction. param_1 à param_n sont les noms des paramètres,
valeur_2 à valeur_n sont les valeurs par défaut des paramètres param_2 à param_n. La seule
contrainte lors de cette définition est que si une valeur par défaut est spécifiée pour un paramètre,
alors tous ceux qui suivent devront eux aussi avoir une valeur par défaut.
Exemple :
def commander_carte_orange (nom, prenom, paiement = "carte", nombre = 1, zone = 2):
print "nom : ", nom
print "prénom : ", prenom
print "paiement : ", paiement
print "nombre : ", nombre
print "zone :", zone
Il est impossible qu’un paramètre sans valeur par défaut associée se situe après un paramètre dont une
valeur par défaut est précisée. Le programme suivant ne pourra être exécuté.
def commander_carte_orange (nom, prenom, paiement = "carte", nombre = 1, zone):
print "nom : ", nom
# ...
L’explication provient du fait que la valeur par défaut est une liste qui n’est pas recréée à chaque appel :
c’est la même liste à chaque fois que la fonction est appelée sans paramètre. Pour remédier à cela, il
faudrait écrire :
import copy
def fonction (l = [0,0]) :
l = copy.copy (l)
l [0] += 1
return l
L’exercice 13.4.7 (page 356) propose un exemple plus complet, voire retors.
Où fonction_nom est le nom de la fonction, param_1 à param_n sont les noms des paramètres,
valeur_1 à valeur_n sont les valeurs que reçoivent ces paramètres. Avec cette syntaxe, l’ordre
d’écriture n’importe pas. La valeur valeur_i sera toujours attribuée à param_i. Les variables x_1 à
x_n reçoivent les résultats retournés par la fonction. L’ordre des résultats ne peut pas être changé.
S’il y a plusieurs résultats retournés, il est impossible de choisir lesquels conserver : soit tous, soit
aucun.
Exemple :
def identite (nom, prenom):
print "nom : ", nom, " prénom : ", prenom
Cette possibilité est intéressante surtout lorsqu’il y a de nombreux paramètres par défaut et que seule la
valeur d’un des derniers paramètres doit être changée.
def commander_carte_orange (paiement = "carte", nombre = 1, zone = 2):
print "paiement : ", paiement
print "nombre : ", nombre
print "zone :", zone
Le petit programme précédent est syntaxiquement correct mais son exécution génère une erreur parce que
la seconde définition de la fonction fonction efface la première.
Traceback (most recent call last):
File "cours4.py", line 7, in ?
print fonction (5,6)
TypeError: fonction() takes exactly 3 arguments (2 given)
4.4.6 Commentaires
Le langage Python propose une fonction help qui retourne pour chaque fonction un commentaire ou mode
d’emploi qui indique comment se servir de cette fonction. L’exemple suivant affiche le commentaire associé
à la fonction round.
>>> help (round)
round(...)
round(number[, ndigits]) -> floating point number
Lorsqu’on utilise cette fonction help sur la fonction coordonnees_polaires définie dans l’exemple du
paragraphe précédent 4.4.2, le message affiché n’est pas des plus explicites.
>>> help (coordonnees_polaires)
coordonnees_polaires(x, y)
Pour changer ce message, il suffit d’ajouter en première ligne du code de la fonction une chaîne de carac-
tères.
import math
def coordonnees_polaires (x,y):
"""convertit des coordonnées cartésiennes en coordonnées polaires
(x,y) --> (pho,theta)"""
rho = math.sqrt(x*x+y*y)
theta = math.atan2 (y,x)
return rho, theta
help (coordonnees_polaires)
coordonnees_polaires(x, y)
convertit des coordonnées cartésiennes en coordonnées polaires
(x,y) --> (pho,theta)
Il est conseillé d’écrire ce commentaire pour toute nouvelle fonction avant même que son corps ne soit
écrit. L’expérience montre qu’on oublie souvent de l’écrire après.
4. Syntaxe du langage Python (boucles, tests, fonctions) 67
def somme_n_premier_terme(n,liste):
"""calcul la somme des n premiers termes d’une liste"""
somme = 0
for i in liste:
somme += i
n -= 1 # modification de n (type immuable)
if n <= 0: break
liste[0] = 0 # modification de liste (type modifiable)
return somme
l = [1,2,3,4]
nb = 3
print "avant la fonction ",nb,l # affiche avant la fonction 3 [1, 2, 3, 4]
s = somme_n_premier_terme (nb,l)
print "après la fonction ",nb,l # affiche après la fonction 3 [0, 2, 3, 4]
print "somme : ", s # affiche somme : 6
liste = [0,1,2]
print liste # affiche [0,1,2]
fonction (liste)
print liste # affiche [0,1,2]
Il faut considérer dans ce programme que la fonction fonction reçoit un paramètre appelé liste mais
utilise tout de suite cet identificateur pour l’associer à un contenu différent. L’identificateur liste est en
quelque sorte passé du statut de paramètre à celui de variable locale. La fonction associe une valeur à
liste - ici, une liste vide - sans toucher à la valeur que cet identificateur désignait précédemment.
Le programme qui suit est différent du précédent mais produit les mêmes effets. Ceci s’explique par le fait
que le mot-clé del ne supprime pas le contenu d’une variable mais seulement son identificateur. Le langage
Python détecte ensuite qu’un objet n’est plus désigné par aucun identificateur pour le supprimer. Cette
remarque est à rapprocher de celles du paragraphe 5.6.
4. Syntaxe du langage Python (boucles, tests, fonctions) 68
liste = [0,1,2]
print liste # affiche [0,1,2]
fonction (liste)
print liste # affiche [0,1,2]
Le programme qui suit permet cette fois-ci de vider la liste liste passée en paramètre à la fonction
fonction. La seule instruction de cette fonction modifie vraiment le contenu désigné par l’identificateur
liste et cela se vérifie après l’exécution de cette fonction.
liste = [0,1,2]
print liste # affiche [0,1,2]
fonction (liste)
print liste # affiche []
La fonction récursive la plus fréquemment citée en exemple est la fonction factorielle. Celle-ci met en
évidence les deux composantes d’une fonction récursive, la récursion proprement dite et la condition
d’arrêt.
def factorielle(n):
if n == 0 : return 1
else : return n * factorielle(n-1)
La dernière ligne de la fonction factorielle est la récursion tandis que la précédente est la condition
d’arrêt, sans laquelle la fonction ne cesserait de s’appeler, empêchant le programme de terminer son
exécution. Si celle-ci est mal spécifiée ou absente, l’interpréteur Python affiche une suite ininterrompue de
messages. Python n’autorise pas plus de 1000 appels récursifs : factorielle(999) provoque nécessairement
une erreur d’exécution même si la condition d’arrêt est bien spécifiée.
Traceback (most recent call last):
File "fact.py", line 5, in <module>
factorielle(999)
File "fact.py", line 3, in factorielle
else : return n * factorielle(n-1)
File "fact.py", line 3, in factorielle
else : return n * factorielle(n-1)
...
La liste des messages d’erreurs est aussi longue qu’il y a eu d’appels à la fonction récursive. Dans ce cas,
il faut transformer cette fonction en une fonction non récursive équivalente, ce qui est toujours possible.
def factorielle_non_recursive (n) :
r = 1
for i in range (2, n+1) :
r *= i
return r
4. Syntaxe du langage Python (boucles, tests, fonctions) 69
4.4.9 Portée
4.4.9.1 Portée des variables, des paramètres
Lorsqu’on définit une variable, elle n’est pas utilisable partout dans le programme. Par exemple, elle n’est
pas utilisable avant d’avoir été déclarée au moyen d’une affectation. Le court programme suivant déclenche
une erreur.
print x # déclenche une erreur
Il est également impossible d’utiliser une variable à l’extérieur d’une fonction où elle a été déclarée.
Plusieurs fonctions peuvent ainsi utiliser le même nom de variable sans qu’à aucun moment, il n’y ait
confusion. Le programme suivant déclenche une erreur identique à celle reproduite ci-dessus.
def portee_variable(x):
var = x
print var
portee_variable(3)
print var # déclenche une erreur car var est déclarée dans
# la fonction portee_variable
Une variable n’a donc d’existence que dans la fonction dans laquelle elle est déclarée. On appelle ce type
de variable une variable locale. Par défaut, toute variable utilisée dans une fonction est une variable locale.
Par opposition aux variables locales, on définit les variables globales qui sont déclarées à l’extérieur de
toute fonction.
L’exemple suivant mélange variable locale et variable globale. L’identificateur n est utilisé à la fois pour
désigner une variable globale égale à 1 et une variable locale égale à 1. A l’intérieur de la fonction, n désigne
la variable locale égale à 2. A l’extérieur de la fonction, n désigne la variable globale égale à 1.
n = 1 # déclaration d’une variable globale
def locale_globale():
n = 2 # déclaration d’une variable locale
print n # affiche le contenu de la variable locale
print n # affiche 1
locale_globale() # affiche 2
print n # affiche 1
4. Syntaxe du langage Python (boucles, tests, fonctions) 70
Il est possible de faire référence aux variables globales dans une fonction par l’intermédiaire du mot-clé
global. Celui-ci indique à la fonction que l’identificateur n n’est plus une variable locale mais désigne une
variable globale déjà déclarée.
n = 1 # déclaration d’une variable globale
def locale_globale():
global n # cette ligne indique que n désigne la variable globale
n = 2 # change le contenu de la variable globale
print n # affiche le contenu de la variable globale
print n # affiche 1
locale_globale() # affiche 2
print n # affiche 2
Cette possibilité est à éviter le plus possible car on peut considérer que locale_globale est en fait une
fonction avec un paramètre caché. La fonction locale_globale n’est plus indépendante des autres fonctions
puisqu’elle modifie une des données du programme.
Le langage Python considère les fonctions également comme des variables d’un type particulier. La portée
des fonctions obéit aux mêmes règles que celles des variables. Une fonction ne peut être appelée que si elle
a été définie avant son appel.
print type(factorielle) # affiche <type ’function’>
Comme il est possible de déclarer des variables locales, il est également possible de définir des fonctions
locales ou fonctions imbriquées. Une fonction locale n’est appelable qu’à l’intérieur de la fonction dans
laquelle elle est définie. Dans l’exemple suivant, la fonction affiche_pair inclut une fonction locale qui
n’est appelable que par cette fonction affiche_pair.
def affiche_pair():
def fonction_locale(i): # fonction locale ou imbriquée
if i % 2 == 0 : return True
else : return False
for i in range(0,10):
if fonction_locale(i):
print i
affiche_pair()
fonction_locale(5) # l’appel à cette fonction locale
# déclenche une erreur d’exécution
A l’intérieur d’une fonction locale, le mot-clé global désigne toujours les variables globales du programme
et non les variables de la fonction dans laquelle cette sous-fonction est définie.
Où fonction est un nom de fonction, param_1 à param_n sont des paramètres de la fonction, liste est
le nom de la liste qui doit recevoir la liste des valeurs seules envoyées à la fonction et qui suivent les
paramètres (plus précisément, c’est un tuple), dictionnaire reçoit la liste des couples (identificateur,
valeur).
Où fonction est un nom de fonction, valeur_1 à valeur_n sont les valeurs associées aux para-
mètres param_1 à param_n, liste_valeur_1 à liste_valeur_p formeront la liste liste, les couples
nom_1 : v_1 à nom_q : v_q formeront le dictionnaire dictionnaire.
Exemple :
def fonction(p,*l,**d):
print "p = ",p
print "liste (tuple) l :", l
print "dictionnaire d :", d
Ce programme affiche :
p = 1
liste l : (2, 3)
dictionnaire d : {’a’: 5, ’b’: 6}
A l’instar des paramètres par défaut, la seule contrainte de cette écriture est la nécessité de respecter
l’ordre dans lequel les informations doivent apparaître. Lors de l’appel, les valeurs sans précision de nom
de paramètre seront placées dans une liste (ici le tuple l). Les valeurs associées à un nom de paramètre
seront placées dans un dictionnaire (ici d). Les valeurs par défaut sont obligatoirement placées après les
paramètres non nommés explicitement.
Une fonction qui accepte des paramètres en nombre variable peut à son tour appeler une autre fonction
acceptant des paramètres en nombre variable. Il faut pour cela se servir du symbole ∗ afin de transmettre
à fonction les valeurs reçues par fonction2.
def fonction(p,*l,**d):
print "p = ",p
print "liste l :", l
print "dictionnaire d :", d
fonction2 (1,2,3,a=5,b=6)
Le programme affiche :
4. Syntaxe du langage Python (boucles, tests, fonctions) 72
p = 1
liste l : (2, 3, 4)
dictionnaire d : {’a’: 5, ’c’: 5, ’b’: 6}
nom_fonction est le nom de la fonction, param_1 à param_n sont les paramètres de cette fonction
(ils peuvent également recevoir des valeurs par défaut), expression est l’expression retournée par la
fonction.
L’exemple suivant utilise cette écriture pour définir la fonction min retournant le plus petit entre deux
nombres positifs.
min = lambda x,y : (abs (x+y) - abs (x-y))/2
Pour que le programme affiche les entiers de 1 à 10, il faut préciser à la fonction lambda une variable y
égale à a au moment de la création de la fonction et qui sera intégrée au contexte de la fonction lambda :
fs = []
for a in range (0,10) :
f = lambda x,y=a : x + y # ligne changée
fs.append (f)
for f in fs :
print (f(1))
de son exécution exactement au même endroit avec des variables locales inchangées. Le mot-clé return
ne doit pas être utilisé. Ces fonctions ou générateurs sont utilisées en couple avec le mot-clé for pour
simuler un ensemble. L’exemple suivant implémente une fonction fonction_yield qui simule l’ensemble
des entiers compris entre 0 et n exclu.
def fonction_yield(n):
i = 0
while i < n-1:
print "yield 1" # affichage : pour voir ce que fait le programme
yield i # arrête la fonction qui reprendra
i = i+1 # à la ligne suivante lors du prochain appel
print "yield 2" # affichage : pour voir ce que fait le programme
yield i # arrête la fonction qui ne reprendra pas
# lors du prochain appel car le code de la fonction
# prend fin ici
for a in fonction_yield(2):
print a # affiche tous les éléments que retourne la
# fonction fonction_yield, elle simule la liste
# [0,1]
print "-----------------------------------------------"
for a in fonction_yield(3):
print a # nouvel appel, l’exécution reprend
# au début de la fonction,
# affiche tous les éléments que retourne la
# fonction fonction_yield, elle simule la liste
# [0,1,2]
Le programme affiche tous les entiers compris entre 0 et 4 inclus ainsi que le texte ”yield 1” ou ”yield 2”
selon l’instruction yield qui a retourné le résultat. Lorsque la fonction a finalement terminé son exécution,
le prochain appel agit comme si c’était la première fois qu’on l’appelait.
yield 1
0
yield 2
1
-----------------------------------------------
yield 1
0
yield 1
1
yield 2
2
Cette fonction a déjà été abordée lors des paragraphes 3.4.1 (paragraphe 3.4.2, page 49). Un exemple a
déjà été présenté page 49. Elle évalue toute chaîne de caractères contenant une expression écrite avec la
syntaxe du langage Python. Cette expression peut utiliser toute variable ou toute fonction accessible au
moment où est appelée la fonction eval.
4. Syntaxe du langage Python (boucles, tests, fonctions) 74
x = 3
y = 4
print eval ("x*x+y*y+2*x*y") # affiche 49
print (x+y)**2 # affiche 49
Si l’expression envoyée à la fonction eval inclut une variable non définie, l’interpréteur Python génère une
erreur comme le montre l’exemple suivant.
x = 3
y = 4
print eval ("x*x+y*y+2*x*y+z")
L’erreur se produit dans une chaîne de caractères traduite en programme informatique, c’est pourquoi
l’interpréteur ne peut pas situer l’erreur dans un fichier. L’erreur ne se produit dans aucun fichier, cette
chaîne de caractères pourrait être définie dans un autre.
Plus complète que la fonction eval, la fonction compile permet d’ajouter une ou plusieurs fonctions au
programme, celle-ci étant définie par une chaîne de caractères. Le code est d’abord compilé (fonction
compile) puis incorporé au programme (fonction exec) comme le montre l’exemple suivant.
import math
str = """def coordonnees_polaires (x,y):
rho = math.sqrt(x*x+y*y)
theta = math.atan2 (y,x)
return rho, theta""" # fonction définie par une chaîne de caractères
La fonction compile prend en fait trois arguments. Le premier est la chaîne de caractères contenant le code
à compiler. Le second paramètre ("" dans l’exemple) contient un nom de fichier dans lequel seront placées
les erreurs de compilation. Le troisième paramètre est une chaîne de caractères à choisir parmi "exec" ou
"eval". Selon ce choix, ce sera la fonction exec ou eval qui devra être utilisée pour agréger le résultat de la
fonction compile au programme. L’exemple suivant donne un exemple d’utilisation de la fonction compile
avec la fonction eval.
import math
str = """math.sqrt(x*x+y*y)""" # expression définie par une chaîne de caractères
4.5 Indentation
L’indentation est synonyme de décalage. Pour toute boucle, test, fonction, et plus tard, toute définition
de classe, le fait d’indenter ou décaler les lignes permet de définir une dépendance d’un bloc de lignes par
4. Syntaxe du langage Python (boucles, tests, fonctions) 75
rapport à un autre. Les lignes indentées par rapport à une boucle for dépendent de celle-ci puisqu’elle
seront exécutées à chaque passage dans la boucle. Les lignes indentées par rapport au mot-clé def sont
considérées comme faisant partie du corps de la fonction. La remarque 4.4 page 53 précise l’erreur que
l’interpréteur Python retourne en cas de mauvaise indentation.
Contrairement à d’autres langages comme le C ou PERL, Python n’utilise pas de délimiteurs pour regrou-
per les lignes. L’indentation, souvent présentée comme un moyen de rendre les programmes plus lisibles,
est ici intégrée à la syntaxe du langage. Il n’y a pas non plus de délimiteurs entre deux instructions autre
qu’un passage à la ligne. Le caractère \ placé à la fin d’une ligne permet de continuer l’écriture d’une
instruction à la ligne suivante.
Elle peut aider à simplifier l’écriture lorsque plusieurs listes sont impliquées. Ici encore, les deux dernières
lignes sont équivalentes.
def addition (x,y) : return x + y
l = [0,3,4,4,5,6]
m = [1,3,4,5,6,8]
print [ addition (l [i], m [i]) for i in range (0, len (l)) ]
print map (addition, l, m) # affiche [1, 6, 8, 9, 11, 14]
Il est possible de substituer None à la fonction f pour obtenir l’équivalent de la fonction zip.
print map (None, l,m) # affiche [(0, 1), (3, 3), (4, 4), (4, 5), (5, 6), (6, 8)]
print zip (l,m) # affiche [(0, 1), (3, 3), (4, 4), (4, 5), (5, 6), (6, 8)]
Comme pour les dictionnaires, la fonction sorted permet de parcourir les éléments d’une liste de façon
ordonnée. Les deux exemples qui suivent sont presque équivalents. Dans le second, la liste l demeure
inchangée alors qu’elle est triée dans le premier programme.
l = [ 4, 5, 3, -6, 7, 9] l = [ 4, 5, 3, -6, 7, 9]
l.sort ()
for n in l : for n in sorted (l) :
print n print n
La fonction enumerate permet d’éviter l’emploi de la fonction range ou xrange lorsqu’on souhaite parcourir
une liste alors que l’indice et l’élément sont nécessaires.
l = [ 4, 5, 3, -6, 7, 9] l = [ 4, 5, 3, -6, 7, 9]
for i in xrange (0, len (l)) : for i,v in enumerate (l) :
print i, l [i] print i, v
4. Syntaxe du langage Python (boucles, tests, fonctions) 76
Néanmoins, la fonction recherche peut être adaptée pour rechercher la première valeur trouvée parmi deux
possibles, ce qu’il n’est pas possible de faire avec la méthode index.
def recherche (li, c,d) :
for i,v in enumerate (li) :
if v in [c,d] : return i
return -1
li = [ 45, 32, 43, 56 ]
print recherche (li, 43, 32) # affiche 1
Ce court exemple montre qu’il est utile de connaître quelques algorithmes simples. Ils ne sont pas forcément
les plus efficaces mais ils aident à construire des programmes plus rapidement et à obtenir un résultat. S’il
est positif alors il sera toujours temps de se pencher sur l’optimisation du programme pour qu’il soit plus
efficace.
Pour éviter la boucle, on peut utiliser l’astuce décrite au paragraphe 4.7.7 qui consiste à former une liste
de couples avec la position initiale :
k = [ (v,i) for i,v in enumerate (li) ]
m = max (k) [1]
Il arrive fréquemment qu’on ne doive pas chercher le maximum d’une liste mais le maximum au sein
d’un sous-ensemble de cette liste. Dans l’exemple qui suit, on cherche le tuple dont la première valeur est
maximale et dont la seconde valeur est égale à 1.
li = [ (0,0), (434,0), (43,1), (6436,1), (5,0) ]
m = -1 # -1 car le premier élément peut ne pas faire partie du sous-ensemble
for i in range (0, len (li)) :
if li [i][1] == 0 and (m == -1 or li [m][0] < li [i][0]) : m = i
li = range (0,100,2) 10
print recherche_dichotomique (li, 48) # affiche 24
print recherche_dichotomique (li, 49) # affiche -1
L’opération inverse :
4.7.5 Somme
Le calcul d’une somme fait toujours intervenir une boucle car le langage Python ne peut faire des additions
qu’avec deux nombres. Le schéma est toujours le même : initialisation et boucle.
li = [ 0, 434, 43, 6456 ]
s = 0 # initialisation
for l in li : # boucle
s += l # addition
Ce code est équivalent à l’instruction sum(li). Dans ce cas où la somme intègre le résultat d’une fonction
et non les éléments d’une liste, il faudrait écrire :
def fonction (x) : return x*x
s = 0
for l in li : s += fonction (l)
Et ces deux lignes pourraient être résu- s = sum ( [fonction (l) for l in li] )
mées en une seule grâce à l’une de ces
s = sum ( map (fonction, li) )
deux instructions.
L’avantage de la solution avec la boucle est qu’elle évite la création d’une liste intermédiaire, c’est un point
à prendre en compte si la liste sur laquelle opère la somme est volumineuse. Il peut être intéressant de
regarder l’exercice 13.1.9 page 330.
4. Syntaxe du langage Python (boucles, tests, fonctions) 79
4.7.6 Tri
Le tri est une opération fréquente. On n’a pas toujours le temps de programmer le tri le plus efficace comme
un tri quicksort et un tri plus simple suffit la plupart du temps. Le tri suivant consiste à recherche le plus
petit élément puis à échanger sa place avec le premier élément du tableau du tableau. On recommence la
même procédure à partir de la seconde position, puis la troisième et ainsi de suite jusqu’à la fin du tableau.
La méthode sort tri également une liste mais selon un algorithme plus efficace que celui-ci dont la logique
est présentée par l’exercice 11.5.1, page 227. Ceci explique pourquoi on hésite toujours à programmer un
tri quitte à avoir recours à une astuce telle que celle présentées au paragraphe suivant.
La liste [p[1] for p in pos] correspond à l’ensemble des positions initiales des éléments de la liste tab. Les
deux lignes qui suivent permettent d’en déduire la position de chaque élément dans l’ensemble trié. ordre[i]
est le rang de l’élément d’indice i avant le tri.
ordre = range (0, len (pos))
for i in xrange (0, len (pos)) : ordre [pos [i][1]] = i
4.7.8 Comptage
On souhaite ici compter le nombre d’occurrences de chaque élément d’un tableau. Par exemple, on pourrait
connaître par ce moyen la popularité d’un mot dans un discours politique ou l’étendue du vocabulaire
utilisé. L’exemple suivant compte les mots d’une liste de mots.
li = ["un", "deux", "un", "trois"]
d = { }
for l in li :
if l not in d : d [l] = 1
else : d [l] += 1
print d # affiche {’un’: 2, ’trois’: 1, ’deux’: 1}
La structure la plus appropriée ici est un dictionnaire puisqu’on cherche à associer une valeur à un élément
d’une liste qui peut être de tout type. Si la liste contient des éléments de type modifiable comme une
liste, il faudrait convertir ceux-ci en un type immuable comme une chaîne de caractères. L’exemple suivant
illustre ce cas en comptant les occurrences des lignes d’une matrice.
4. Syntaxe du langage Python (boucles, tests, fonctions) 80
On peut également vouloir non pas compter le nombre d’occurrence mais mémoriser les positions des
éléments tous identiques. On doit utiliser un dictionnaire de listes :
li = ["un", "deux", "un", "trois"]
d = { }
for i,v in enumerate (li) :
if v not in d : d [v] = [ i ]
else : d [v].append (i)
print d # affiche {’un’: [0, 2], ’trois’: [3], ’deux’: [1]}
Le programme suivant fait l’inverse. Il faut faire attention à la position des crochets et l’ordre des boucles
for.
nc = len (mat [0])
mat = [ [ lin [i * nc + j] for j in range (0, len (mat [i])) ] \
for i in range (0, len (mat)) ]
l = [0,1,2,3]
print l # affiche [0, 1, 2, 3]
Imaginons qu’une banque détienne un fichier contenant des informations sur ses clients et qu’il soit impos-
sible pour un client d’avoir accès directement à ces informations. Toutefois, il lui est en théorie possible
de demander à son banquier quelles sont les informations le concernant détenues par sa banque. Il est en
théorie également possible de les rectifier s’il estime qu’elles sont incorrectes. 1 .
On peut comparer cette banque à un objet qui possède des informations et des moyens permettant de lire
ces informations et de les modifier. Vu de l’extérieur, cette banque cache son fonctionnement interne et les
informations dont elle dispose, mais propose des services à ses utilisateurs.
On peut considérer la banque comme un objet au sens informatique. Ce terme désigne une entité possédant
des données et des méthodes permettant de les manipuler. Plus concrètement, une classe est un assemblage
de variables appelées attributs et de fonctions appelées méthodes. L’ensemble des propriétés associées aux
classes est regroupé sous la désignation de programmation objet.
Le corps d’une classe peut être vide, inclure des variables ou attributs, des fonctions ou méthodes.
Il est en tout cas indenté de façon à indiquer à l’interpréteur Python les lignes qui forment le corps
de la classe.
Les classes sont l’unique moyen en langage Python de définir de nouveaux types propres à celui qui
programme. Il n’existe pas de type "matrice" ou de type "graphe" en langage Python qui soit prédéfini 2 .
Il est néanmoins possible de les définir au moyen des classes. Une matrice est par exemple un objet qui
inclut les attributs suivant : le nombre de lignes, le nombre de colonnes, les coefficients de la matrice.
Cette matrice inclut aussi des méthodes comme des opérations entre deux matrices telles que l’addition,
la soustraction, la multiplication ou des opérations sur elle-même comme l’inversion, la transposition, la
diagonalisation.
Cette liste n’est pas exhaustive, elle illustre ce que peut être une classe "matrice" - représentation infor-
matique d’un objet "matrice" -, un type complexe incluant des informations de types variés (entier pour
les dimensions, réels pour les coefficients), et des méthodes propres à cet objet, capables de manipuler ces
1. Tout fichier contenant des données à caractère personnel doit être recensé auprès de la Commission nationale de
l’informatique et des libertés (CNIL). Cet organisme facilite l’accès à ces informations.
2. Les matrices sont définies dans une extension externe numpy (voir le chapitre 7).
5. Classes 82
informations.
Il est tout-à-fait possible de se passer des classes pour rédiger un programme informatique. Leur utilisation
améliore néanmoins sa présentation et la compréhension qu’on peut en avoir. Bien souvent, ceux qui passent
d’un langage uniquement fonctionnel à un langage objet ne font pas marche arrière.
La création d’une variable de type objet est identique à celle des types standards du langage Python :
elle passe par une simple affectation. On appelle aussi cl une instance de la classe nom_classe.
Cette syntaxe est identique à la syntaxe d’appel d’une fonction. La création d’une instance peut également
faire intervenir des paramètres (voir paragraphe 5.4). Le terme instance va de paire avec le terme classe :
L’exemple suivant permet de définir une classe vide. Le mot-clé pass permet de préciser que le corps de la
classe ne contient rien.
class classe_vide:
pass
Il est tout de même possible de définir une instance de la classe classe_vide simplement par l’instruction
suivante :
class classe_vide:
pass
cl = classe_vide ()
Pour savoir si une variable est une instance d’une classe donnée, il faut utiliser la fonction isinstance :
isinstance (cl,classe_vide) # affiche True
5.1.2 Méthodes
Ces données ou attributs sont définis plus loin. Les méthodes sont en fait des fonctions pour lesquelles
la liste des paramètres contient obligatoirement un paramètre explicite qui est l’instance de la classe à
5. Classes 83
laquelle cette méthode est associée. Ce paramètre est le moyen d’accéder aux données de la classe.
A part le premier paramètre qui doit de préférence s’appeler self, la syntaxe de définition d’une
méthode ressemble en tout point à celle d’une fonction. Le corps de la méthode est indenté par
rapport à la déclaration de la méthode, elle-même indentée par rapport à la déclaration de la classe.
L’appel d’une méthode nécessite tout d’abord la création d’une variable. Une fois cette variable créée,
il suffit d’ajouter le symbole "." pour exécuter la méthode. Le paramètre self est ici implicitement
remplacé par cl lors de l’appel.
L’exemple suivant simule le tirage de nombres aléatoires à partir d’une suite définie par récurrence un+1 =
(un ∗A) mod B où A et B sont des entiers très grands. Cette suite n’est pas aléatoire mais son comportement
imite celui d’une suite aléatoire. Le terme un est dans cet exemple contenu dans la variable globale rnd.
rnd = 42
class exemple_classe:
def methode1(self,n):
"""simule la génération d’un nombre aléatoire
compris entre 0 et n-1 inclus"""
global rnd
rnd = 397204094 * rnd % 2147483647
return int (rnd % n)
nb = exemple_classe ()
l = [ nb.methode1(100) for i in range(0,10) ]
print l # affiche [19, 46, 26, 88, 44, 56, 56, 26, 0, 8]
nb2 = exemple_classe ()
l2 = [ nb2.methode1(100) for i in range(0,10) ]
print l2 # affiche [46, 42, 89, 66, 48, 12, 61, 84, 71, 41]
Deux instances nb et nb2 de la classe exemple_classe sont créées, chacune d’elles est utilisée pour générer
aléatoirement dix nombres entiers compris entre 0 et 99 inclus. Les deux listes sont différentes puisque
l’instance nb2 utilise la variable globale rnd précédemment modifiée par l’appel nb.methode1(100).
Remarque 5.9 : méthodes et fonctions
Les méthodes sont des fonctions insérées à l’intérieur d’une classe. La syntaxe de la déclaration d’une
méthode est identique à celle d’une fonction en tenant compte du premier paramètre qui doit impérati-
vement être self. Les paramètres par défaut, l’ordre des paramètres, les nombres variables de paramètres
présentés au paragraphe 4.4 sont des extensions tout autant applicables aux méthodes qu’aux fonctions.
5.1.3 Attributs
Une classe permet en quelque sorte de regrouper ensemble des informations liées. Elles n’ont de sens
qu’ensemble et les méthodes manipulent ces données liées. C’est le cas pour un segment qui est toujours
défini par ces deux extrémités qui ne vont pas l’une sans l’autre.
Le paramètre self n’est pas un mot-clé même si le premier paramètre est le plus souvent appelé
self. Il désigne l’instance de la classe sur laquelle va s’appliquer la méthode. La déclaration d’une
méthode inclut toujours un paramètre self de sorte que self.nom_attribut désigne un attribut de
la classe. nom_attribut seul désignerait une variable locale sans aucun rapport avec un attribut
portant le même nom. Les attributs peuvent être déclarés à l’intérieur de n’importe quelle méthode,
voire à l’extérieur de la classe elle-même.
L’endroit où est déclaré un attribut a peu d’importance pourvu qu’il le soit avant sa première utilisation.
Dans l’exemple qui suit, la méthode methode1 utilise l’attribut rnd sans qu’il ait été créé.
class exemple_classe:
def methode1(self,n):
"""simule la génération d’un nombre aléatoire
compris entre 0 et n-1 inclus"""
self.rnd = 397204094 * self.rnd % 2147483647
return int (self.rnd % n)
nb = exemple_classe ()
l = [ nb.methode1(100) for i in range(0,10) ]
print l
Cet exemple déclenche donc une erreur (ou exception) signifiant que l’attribut rnd n’a pas été créé.
Traceback (most recent call last):
File "cours.py", line 8, in -toplevel-
l = [ nb.methode1(100) for i in range(0,10) ]
File "cours.py", line 4, in methode1
self.rnd = 397204094 * self.rnd % 2147483647
AttributeError: exemple_classe instance has no attribute ’rnd’
Pour remédier à ce problème, il existe plusieurs endroits où il est possible de créer l’attribut rnd. Il est
possible de créer l’attribut à l’intérieur de la méthode methode1. Mais le programme n’a plus le même
sens puisqu’à chaque appel de la méthode methode1, l’attribut rnd reçoit la valeur 42. La liste de nombres
aléatoires contient dix fois la même valeur.
class exemple_classe:
def methode1(self,n):
"""simule la génération d’un nombre aléatoire
compris entre 0 et n-1 inclus"""
self.rnd = 42 # déclaration à l’intérieur de la méthode,
# doit être précédé du mot-clé self
self.rnd = 397204094 * self.rnd % 2147483647
return int (self.rnd % n)
nb = exemple_classe ()
l = [ nb.methode1(100) for i in range(0,10) ]
print l # affiche [19, 19, 19, 19, 19, 19, 19, 19, 19, 19]
Il est possible de créer l’attribut rnd à l’extérieur de la classe. Cette écriture devrait toutefois être évitée
puisque la méthode methode1 ne peut pas être appelée sans que l’attribut rnd ait été ajouté.
class exemple_classe:
def methode1(self,n):
"""simule la génération d’un nombre aléatoire
compris entre 0 et n-1 inclus"""
5. Classes 85
nb = exemple_classe ()
nb.rnd = 42 # déclaration à l’extérieur de la classe,
# indispensable pour utiliser la méthode methode1
l = [ nb.methode1(100) for i in range(0,10) ]
print l # affiche [19, 46, 26, 88, 44, 56, 56, 26, 0, 8]
5.2 Constructeur
L’endroit le plus approprié pour déclarer un attribut est à l’intérieur d’une méthode appelée le constructeur.
S’il est défini, il est implicitement exécuté lors de la création de chaque instance. Le constructeur d’une
classe se présente comme une méthode et suit la même syntaxe à ceci près que son nom est imposé :
__init__. Hormis le premier paramètre, invariablement self, il n’existe pas de contrainte concernant la
liste des paramètres excepté que le constructeur ne doit pas retourner de résultat.
nom_classe est une classe, __init__ est son constructeur, sa syntaxe est la même que celle d’une
méthode sauf que le constructeur ne peut employer l’instruction return.
nom_classe est une classe, valeur_1 à valeur_n sont les valeurs associées aux paramètres param_1
à param_n du constructeur.
L’exemple suivant montre deux classes pour lesquelles un constructeur a été défini. La première n’ajoute
aucun paramètre, la création d’une instance ne nécessite pas de paramètre supplémentaire. La seconde
classe ajoute deux paramètres a et b. Lors de la création d’une instance de la classe classe2, il faut ajouter
deux valeurs.
class classe1:
def __init__(self):
# pas de paramètre supplémentaire
print "constructeur de la classe classe1"
self.n = 1 # ajout de l’attribut n
class classe2:
def __init__(self,a,b):
# deux paramètres supplémentaires
print "constructeur de la classe classe2"
self.n = (a+b)/2 # ajout de l’attribut n
En utilisant un constructeur, l’exemple du paragraphe précédent simulant une suite de variable aléatoire
permet d’obtenir une classe autonome qui ne fait pas appel à une variable globale ni à une déclaration
d’attribut extérieur à la classe.
class exemple_classe:
def __init__ (self) : # constructeur
self.rnd = 42 # on crée l’attribut rnd, identique pour chaque instance
# --> les suites générées auront toutes le même début
def methode1(self,n):
self.rnd = 397204094 * self.rnd % 2147483647
return int (self.rnd % n)
nb = exemple_classe ()
l = [ nb.methode1(100) for i in range(0,10) ]
print l # affiche [19, 46, 26, 88, 44, 56, 56, 26, 0, 8]
nb2 = exemple_classe ()
l2 = [ nb2.methode1(100) for i in range(0,10) ]
print l2 # affiche [19, 46, 26, 88, 44, 56, 56, 26, 0, 8]
De la même manière qu’il existe un constructeur exécuté à chaque création d’instance, il existe un des-
tructeur exécuté à chaque destruction d’instance. Il suffit pour cela de redéfinir la méthode __del__. A
l’inverse d’autres langages comme le C++, cet opérateur est peu utilisé car le Python nettoie automati-
quement les objets qui ne sont plus utilisés ou plus référencés par une variable. Un exemple est donné
page 99.
nb = exemple_classe ()
print nb.__dict__ # affiche {’rnd’: 42}
Ce dictionnaire offre aussi la possibilité de tester si un attribut existe ou non. Dans un des exemples du
paragraphe précédent, l’attribut rnd était créé dans la méthode methode1, sa valeur était alors initialisée
à chaque appel et la fonction retournait sans cesse la même valeur. En testant l’existence de l’attribut
rnd, il est possible de le créer dans la méthode methode1 au premier appel sans que les appels suivants ne
réinitialisent sa valeur à 42.
class exemple_classe:
def methode1(self,n):
if "rnd" not in self.__dict__ : # l’attribut existe-t-il ?
self.rnd = 42 # création de l’attribut
self.__dict__ ["rnd"] = 42 # autre écriture possible
self.rnd = 397204094 * self.rnd % 2147483647
return int (self.rnd % n)
nb = exemple_classe ()
l = [ nb.methode1(100) for i in range(0,10) ]
print l # affiche [19, 46, 26, 88, 44, 56, 56, 26, 0, 8]
5. Classes 87
__module__ Contient le nom du module dans lequel est incluse la classe (voir chapitre 7).
Contient le nom de la classe de l’instance. Ce nom est précédé du nom du module suivi
__class__
d’un point.
__dict__ Contient la liste des attributs de l’instance (voir paragraphe 5.3.1).
__doc__ Contient un commentaire associé à la classe (voir paragraphe 5.3.3).
class classe_vide:
pass
cl = classe_vide ()
print cl.__module__ # affiche __main__
print cl.__class__ # affiche __main__.classe_vide ()
print cl.__dict__ # affiche {}
print cl.__doc__ # affiche None (voir paragraphe suivant)
print cl.__class__.__doc__ # affiche None
print cl.__class__.__dict__ # affiche {’__module__’: ’__main__’,
# ’__doc__’: None}
print cl.__class__.__name__ # affiche classe_vide
print cl.__class__.__bases__ # affiche ()
class exemple_classe
| simule une suite de nombres aléatoires
|
| Methods defined here:
|
| __init__(self)
5. Classes 88
Pour obtenir seulement le commentaire associé à la classe, il suffit d’écrire l’une des trois lignes suivantes :
La fonction help permet d’accéder à l’aide associée à une fonction, une classe. Il existe des outils qui
permettent de collecter tous ces commentaires pour construire une documentation au format HTML à
l’aide d’outils comme pydoc 3 ou Doxygen 4 . Ces outils sont souvent assez simples d’utilisation.
La fonction dir permet aussi d’obtenir des informations sur la classe. Cette fonction appliquée à la classe
ou à une instance retourne l’ensemble de la liste des attributs et des méthodes. L’exemple suivant utilise la
fonction dir avant et après l’appel de la méthode meth. Etant donné que cette méthode ajoute un attribut,
la fonction dir retourne une liste plus longue après l’appel.
class essai_class:
def meth(self):
x = 6
self.y = 7
a = essai_class()
print dir (a) # affiche [’__doc__’, ’__module__’, ’meth’]
a.meth ()
print dir (a) # affiche [’__doc__’, ’__module__’, ’meth’, ’y’]
print dir (essai_class) # affiche [’__doc__’, ’__module__’, ’meth’]
La fonction dir appliquée à la classe elle-même retourne une liste qui inclut les méthodes et les attributs
déjà déclarés. Elle n’inclut pas ceux qui sont déclarés dans une méthode jamais exécutée jusqu’à présent.
class ensemble_element :
class element :
def __init__ (self) :
self.x, self.y, self.z = 0,0,0
f = ensemble_element ()
f.all [0].x, f.all [0].y, f.all [0].z = 4.5,1.5,1.5
b = f.barycentre ()
print b.x,b.y,b.z # affiche 1.5 0.5 0.5
Pour créer une instance de la classe element, il faut faire précéder son nom de la classe où elle est déclarée :
b = ensemble_element.element() comme c’est le cas dans la méthode barycentre par exemple.
L’addition n’est pas le seul symbole concerné, le langage Python permet de donner un sens à tous les
opérateurs numériques et d’autres reliés à des fonctions du langage comme len ou max.
5.4.1 Opérateurs
Le programme suivant contient une classe définissant un nombre complexe. La méthode ajoute définit ce
qu’est une addition entre nombres complexes.
class nombre_complexe:
def __init__ (self, a = 0, b= 0) : self.a, self.b = a,b
def get_module (self) : return math.sqrt (self.a * self.a + self.b * self.b)
c1 = nombre_complexe (0,1)
c2 = nombre_complexe (1,0)
c = c1.ajoute (c2) # c = c1 + c2
print c.a, c.b
Toutefois, on aimerait bien écrire simplement c = c1 + c2 au lieu de c = c1.ajoute(c2) car cette syntaxe
est plus facile à lire et surtout plus intuitive. Le langage Python offre cette possibilité. Il existe en effet
des méthodes clés dont l’implémentation définit ce qui doit être fait dans le cas d’une addition, d’une
comparaison, d’un affichage, ... A l’instar du constructeur, toutes ces méthodes clés, qu’on appelle des
opérateurs, sont encadrées par deux blancs soulignés, leur déclaration suit invariablement le même schéma.
Voici celui de l’opérateur __add__ qui décrit ce qu’il faut faire pour une addition.
nom_classe est une classe. L’opérateur __add__ définit l’addition entre l’instance self et l’instance
autre et retourne une instance de la classe nom_classe.
Le programme suivant reprend le précédent de manière à ce que l’addition de deux nombres complexes
soit dorénavant une syntaxe correcte.
5. Classes 90
class nombre_complexe:
def __init__ (self, a = 0, b= 0) : self.a, self.b = a,b
def get_module (self) : return math.sqrt (self.a * self.a + self.b * self.b)
c1 = nombre_complexe (0,1)
c2 = nombre_complexe (1,0)
c = c1 + c2 # cette expression est maintenant syntaxiquement correcte
c = c1.__add__ (c2) # même ligne que la précédente mais écrite explicitement
print c.a, c.b
L’avant dernière ligne appelant la méthode __add__ transcrit de façon explicite ce que le langage Py-
thon fait lorsqu’il rencontre un opérateur + qui s’applique à des classes. Plus précisément, c1 et c2 pour-
raient être de classes différentes, l’expression serait encore valide du moment que la classe dont dépend
c1 a redéfini la méthode __add__. Chaque opérateur possède sa méthode-clé associée. L’opérateur +=,
différent de + est associé à la méthode-clé __iadd__.
nom_classe est une classe. L’opérateur __iadd__ définit l’addition entre l’instance self et l’instance
autre. L’instance self est modifiée pour recevoir le résultat. L’opérateur retourne invariablement
l’instance modifiée self.
On étoffe la classe nombre_complexe à l’aide de l’opérateur __iadd__.
class nombre_complexe:
def __init__ (self, a = 0, b= 0) : self.a, self.b = a,b
def get_module (self) : return math.sqrt (self.a * self.a + self.b * self.b)
def __add__(self, c) : return nombre_complexe (self.a + c.a, self.b + c.b)
def __iadd__(self, c) :
self.a += c.a
self.b += c.b
return self
c1 = nombre_complexe (0,1)
c2 = nombre_complexe (1,0)
c1 += c2 # utilisation de l’opérateur +=
c1.__iadd__ (c2) # c’est la transcription explicite de la ligne précédente
print c1.a, c1.b
Un autre opérateur souvent utilisé est __str__ qui permet de redéfinir l’affichage d’un objet lors d’un
appel à l’instruction print.
nom_classe est une classe. L’opérateur __str__ construit une chaîne de caractères qu’il retourne
comme résultat de façon à être affiché.
L’exemple suivant reprend la classe nombre_complexe pour que l’instruction print affiche un nombre com-
plexe sous la forme a + ib.
class nombre_complexe:
def __init__ (self, a = 0, b= 0) : self.a, self.b = a,b
5. Classes 91
c1 = nombre_complexe (0,1)
c2 = nombre_complexe (1,0)
c3 = c1 + c2
print c3 # affiche 1.000000 + 1.000000 i
Il existe de nombreux opérateurs qu’il est possible de définir. La table 5.1 (page 117) présente les plus
utilisés. Parmi ceux-là, on peut s’attarder sur les opérateurs __getitem__ et __setitem__, ils redéfi-
nissent l’opérateur [] permettant d’accéder à un élément d’une liste ou d’un dictionnaire. Le premier,
__getitem__ est utilisé lors d’un calcul, un affichage. Le second, __setitem__, est utilisé pour affecter
une valeur.
L’exemple suivant définit un point de l’espace avec trois coordonnées. Il redéfinit ou surcharge les opérateurs
__getitem__ et __setitem__ de manière à pouvoir accéder aux coordonnées de la classe point_espace
qui définit un point dans l’espace. En règle générale, lorsque les indices ne sont pas corrects, ces deux
opérateurs lèvent l’exception IndexError (voir le chapitre 6).
class point_espace:
def __init__ (self, x,y,z): self._x, self._y, self._z = x,y,z
def __getitem__(self,i):
if i == 0 : return self._x
if i == 1 : return self._y
if i == 2 : return self._z
# pour tous les autres cas --> erreur
raise IndexError ("indice impossible, 0,1,2 autorisés")
def __setitem__(self,i,x):
if i == 0 : self._x = x
elif i == 1 : self._y = y
elif i == 2 : self._z = z
# pour tous les autres cas --> erreur
raise IndexError ("indice impossible, 0,1,2 autorisés")
def __str__(self):
return "(%f,%f,%f)" % (self._x, self._y, self._z)
a = point_espace (1,-2,3)
Par le biais de l’exception IndexError, les expressions a[i] avec i 6= 0, 1, 2 sont impossibles et arrêtent le
programme par un message comme celui qui suit obtenu après l’interprétation de print a [4] :
Traceback (most recent call last):
File "point_espace.py", line 31, in ?
print a [4]
File "point_espace.py", line 13, in __getitem__
raise IndexError, "indice impossible, 0,1,2 autorisés"
IndexError: indice impossible, 0,1,2 autorisés
5.4.2 Itérateurs
L’opérateur __iter__ permet de définir ce qu’on appelle un itérateur. C’est un objet qui permet d’en
explorer un autre, comme une liste ou un dictionnaire. Un itérateur est un objet qui désigne un élément
d’un ensemble à parcourir et qui connaît l’élément suivant à visiter. Il doit pour cela contenir une référence
5. Classes 92
à l’objet qu’il doit explorer et inclure une méthode next qui retourne l’élément suivant ou lève une exception
si l’élément actuel est le dernier.
Par exemple, on cherche à explorer tous les éléments d’un objet de type point_espace défini au paragraphe
précédent. Cette exploration doit s’effectuer au moyen d’une boucle for.
a = point_espace (1,-2,3)
for x in a:
print x # affiche successivement 1,-2,3
Cette boucle cache en fait l’utilisation d’un itérateur qui apparaît explicitement dans l’exemple suivant
équivalent au précédent (voir paragraphe 4.3.2.3, page 59).
a = point_espace (1,-2,3)
it = iter (a)
while True:
try : print it.next ()
except StopIteration : break
Afin que cet extrait de programme fonctionne, il faut définir un itérateur pour la classe point_espace.
Cet itérateur doit inclure la méthode next. La classe point_espace doit quant à elle définir l’opérateur
__iter__ pour retourner l’itérateur qui permettra de l’explorer.
class point_espace:
def __init__ (self, x,y,z):
self._x, self._y, self._z = x,y,z
def __str__(self):
return "(%f,%f,%f)" % (self._x, self._y, self._z)
def __getitem__(self,i):
if i == 0 : return self._x
if i == 1 : return self._y
if i == 2 : return self._z
# pour tous les autres cas --> erreur
raise IndexError ("indice impossible, 0,1,2 autorisés")
class class_iter:
"""cette classe définit un itérateur pour point_espace"""
def __init__ (self,ins):
"""initialisation, self._ins permet de savoir quelle
instance de point_espace on explore,
self._n mémorise l’indice de l’élément exploré"""
self._n = 0
self._ins = ins
def __iter__(self):
"""opérateur de la classe point_espace, retourne un itérateur
permettant de l’explorer"""
return point_espace.class_iter (self)
a = point_espace (1,-2,3)
for x in a:
print x # affiche successivement 1,-2,3
Cette syntaxe peut paraître fastidieuse mais elle montre de manière explicite le fonctionnement des ité-
rateurs. Cette construction est plus proche de ce que d’autres langages objets proposent. Python offre
néanmoins une syntaxe plus courte avec le mot-clé yield qui permet d’éviter la création de la classe
5. Classes 93
class_iter. Le code de la méthode __iter__ change mais les dernières lignes du programme précédent
qui affichent successivement les éléments de point_espace sont toujours valides.
class point_espace:
def __init_