Vous êtes sur la page 1sur 443

APPRENEZ PROGRAMMER EN

PYTHON

2e
d

iti

on

Vincent Le Goff

Devenez Premium
Tlchargez
les eBooks
Accdez
aux certifications
Tlchargez
les vidos en HD
www.openclassrooms.com/premium

Sauf mention contraire, le contenu de cet ouvrage est publi sous la licence :
Creative Commons BY-NC-SA 2.0
La copie de cet ouvrage est autorise sous rserve du respect des conditions de la licence
Texte complet de la licence disponible sur : http : //creativecommons.org/licenses/by-nc-sa/2.0/fr/
Mentions lgales :
Conception couverture : Sophie Bai
Illustrations chapitres : Fan Jiyong et Sophie Bai
OpenClassrooms 2014 - ISBN : 979-10-90085-78-7

Avant-propos
ai commenc mintresser linformatique, et plus particulirement au monde
de la programmation, au dbut du lyce, il y a maintenant plus de huit ans. Jai
abord ce terrain inconnu avec une grande curiosit. . . qui na pas encore faibli
puisque je suis aujourdhui tudiant INTECH INFO, une cole suprieure dingnierie
informatique ! Au premier abord, la programmation me semblait un monde aride et
froid, rempli dquations compliques et de notions abstraites.

Heureusement, le premier langage avoir attir mon attention sest trouv tre le
Python : un langage la fois simple et extrmement puissant, que je considre aujourdhui comme le meilleur choix quand on souhaite apprendre programmer. Le Python
est dailleurs rest le langage que jutilise le plus dans les projets libres auxquels je
contribue.
Mais Python nest pas quun langage simple : cest un langage puissant. Il existe une
diffrence entre connatre un langage et coder efficacement dans ce langage. Plusieurs
annes de pratique mont t ncessaires pour comprendre pleinement cette diffrence.
Les cours sur le langage Python sadressant aux dbutants ne sont pas rares sur le Web
et beaucoup sont de grande qualit. Toutefois, il en existe trop peu, mon sens, qui
permettent de comprendre la fois la syntaxe et la philosophie du langage.
Mon objectif ici est quaprs avoir lu ce livre, vous sachiez programmer en Python. Et
par programmer , je nentends pas seulement matriser la syntaxe du langage, mais
aussi comprendre sa philosophie.
tant non-voyant, je me suis efforc de rendre ce cours aussi accessible que
possible tous. Ainsi, ne soyez pas surpris si vous y trouvez moins de schmas
et dillustrations que dans dautres cours. Jai fait en sorte que leur prsence
ne soit pas indispensable la comprhension du lecteur.
Pour ceux qui se demandent comment je travaille, jai un ordinateur absolument semblable au vtre. Pour pouvoir lutiliser, jinstalle sur mon systme un logiciel quon
appelle lecteur dcran. Ce lecteur me dicte une bonne partie des informations affiches dans la fentre du logiciel que jutilise, comme le navigateur Internet. Le lecteur,
comme son nom lindique, va lire grce une voix synthtique les informations quil
dtecte sur la fentre et peut galement les transmettre une plage tactile. Cest un

CHAPITRE 0. AVANT-PROPOS
priphrique qui se charge dafficher automatiquement en braille les informations que
lui transmet le lecteur dcran. Avec ces outils, je peux donc me servir dun ordinateur,
aller sur Internet et mme programmer !

Figure 1 La plage tactile et le casque transmettent les informations affiches lcran

Quallez-vous apprendre en lisant ce livre ?


Ce livre sadresse au plus grand nombre :
si le mot programmation ne vous voque rien de prcis, ce livre vous guidera pas
pas dans la dcouverte du monde du programmeur ;
si vous connaissez dj un langage de programmation autre que Python, ce livre
prsente de faon aussi claire que possible la syntaxe de Python et des exemples
dutilisation concrte de ce langage ;
si vous connaissez dj Python, ce cours peut vous servir de support comparatif avec
dautres livres et cours existants ;
si vous enseignez le langage Python, jai espoir que ce livre pourra tre un support
utile, autant pour vous que pour vos tudiants.
Ce livre est divis en cinq parties. Les trois premires parties sont lire dans lordre,
sauf si vous avez dj de solides bases en Python :
1. Introduction Python : cest une introduction au langage de programmation
Python. Vous y apprendrez dabord, si vous lignorez, ce que signifie programii

COMMENT LIRE CE LIVRE ?


mer, ce quest Python et la syntaxe de base du langage.
2. La Programmation Oriente Objet ct utilisateur : aprs avoir vu les
bases de Python, nous allons tudier la faade objet de ce langage. Dans cette
partie, vous apprendrez utiliser les classes que dfinit Python. Ne vous inquitez
pas, les concepts dobjet et de classe seront largement dtaills ici. Donc, si ces
mots ne vous disent rien au premier abord, pas dinquitude !
3. La Programmation Oriente Objet ct dveloppeur : cette partie poursuit lapproche de la faade objet dbute dans la partie prcdente. Cette fois,
cependant, au lieu dtre utilisateur des classes dj dfinies par Python, vous
allez apprendre en crer. L encore, ne vous inquitez pas : nous verrons tous
ces concepts pas pas.
4. Les merveilles de la bibliothque standard : cette partie tudie plus en
dtail certains modules dj dfinis par Python. Vous y apprendrez notament
manipuler les dates et heures, faire des interfaces graphiques, construire une
architecture rseau. . . et bien plus !
5. Annexes : enfin, cette partie regroupe les annexes et rsums du cours. Il sagit
de notions qui ne sont pas absolument ncessaires pour dvelopper en Python
mais que je vous encourage tout de mme lire attentivement.

Comment lire ce livre ?


Suivez lordre des chapitres
Lisez ce livre comme on lit un roman. Il a t conu pour cela.
Contrairement beaucoup de livres techniques o il est courant de lire en diagonale et
de sauter certains chapitres, il est ici trs fortement recommand de suivre lordre du
cours, moins que vous ne soyez dj un peu expriments.

Pratiquez en mme temps


Pratiquez rgulirement. Nattendez pas davoir fini de lire ce livre pour allumer votre
ordinateur et faire vos propres essais.

Utilisez les codes web !


Afin de tirer parti dOpenClassrooms dont ce livre est issu, celui-ci vous propose ce
quon appelle des codes web . Ce sont des codes six chiffres saisir sur une page
dOpenClassrooms pour tre automatiquement redirig vers un site web sans avoir
en recopier ladresse.
Pour utiliser les codes web, rendez-vous sur la page suivante :
http://fr.openclassrooms.com/codeweb.html
iii

CHAPITRE 0. AVANT-PROPOS
Un formulaire vous invite rentrer votre code web. Faites un premier essai avec le code
ci-dessous :


Tester le code web
B
Code web : 123456


Ces codes web ont deux intrts :
ils vous redirigent vers les sites web prsents tout au long du cours, vous permettant
ainsi dobtenir les logiciels dans leur toute dernire version ;
ils vous permettent de tlcharger les codes sources inclus dans ce livre, ce qui vous
vitera davoir recopier certains programmes un peu longs.
Ce systme de redirection nous permet de tenir jour le livre que vous avez entre les
mains sans que vous ayez besoin dacheter systmatiquement chaque nouvelle dition.
Si un site web change dadresse, nous modifierons la redirection mais le code web
utiliser restera le mme. Si un site web disparat, nous vous redirigerons vers une page
dOpenClassrooms expliquant ce qui sest pass et vous proposant une alternative.
En clair, cest un moyen de nous assurer de la prennit de cet ouvrage sans que vous
ayez faire quoi que ce soit !

Remerciements
De nombreuses personnes ont, plus ou moins directement, particip ce livre. Mes
remerciements leurs sont adresss :
ma famille avant tout, qui a su mencourager, dans ce projet comme dans tout
autre, du dbut jusqu la fin ;
aux personnes, trop nombreuses pour que jen dresse ici la liste, qui ont contribu,
par leurs encouragements, leurs remarques et parfois leurs critiques, faire de ce
livre ce quil est ;
lquipe dOpenClassrooms qui a rendu ce projet envisageable et a travaill darrachepied pour quil se concrtise ;
aux membres dOpenClassrooms (Site du Zro lpoque) qui ont contribu sa
correction ou son enrichissement.

iv

Table des matires

Avant-propos

Quallez-vous apprendre en lisant ce livre ? . . . . . . . . . . . . . . . . . . . .

ii

Comment lire ce livre ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

iii

Suivez lordre des chapitres . . . . . . . . . . . . . . . . . . . . . . . . .

iii

Pratiquez en mme temps . . . . . . . . . . . . . . . . . . . . . . . . . .

iii

Utilisez les codes web ! . . . . . . . . . . . . . . . . . . . . . . . . . . . .

iii

Remerciements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

iv

Introduction Python

1 Quest-ce que Python ?

Un langage de programmation ? Quest-ce que cest ? . . . . . . . . . . . . . .

La communication humaine . . . . . . . . . . . . . . . . . . . . . . . . .

Mon ordinateur communique aussi ! . . . . . . . . . . . . . . . . . . . . .

Pour la petite histoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

quoi peut servir Python ? . . . . . . . . . . . . . . . . . . . . . . . . .

Un langage de programmation interprt . . . . . . . . . . . . . . . . . .

Diffrentes versions de Python

. . . . . . . . . . . . . . . . . . . . . . .

Installer Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Sous Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Sous Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Sous Mac OS X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

TABLE DES MATIRES


Lancer Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2 Premiers pas avec linterprteur de commandes Python

13

O est-ce quon est, l ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14

Vos premires instructions : un peu de calcul mental pour lordinateur . . . .

15

Saisir un nombre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15

Oprations courantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16

3 Le monde merveilleux des variables


Cest quoi, une variable ? Et quoi cela sert-il ? . . . . . . . . . . . . . . . . .
Cest quoi, une variable ?

19
20

. . . . . . . . . . . . . . . . . . . . . . . . . .

20

Comment cela fonctionne-t-il ? . . . . . . . . . . . . . . . . . . . . . . .

20

Les types de donnes en Python . . . . . . . . . . . . . . . . . . . . . . . . .

22

Quentend-on par type de donne ? . . . . . . . . . . . . . . . . . . .

22

Les diffrents types de donnes . . . . . . . . . . . . . . . . . . . . . . .

23

Un petit bonus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

25

Quelques trucs et astuces pour vous faciliter la vie . . . . . . . . . . . .

25

Premire utilisation des fonctions . . . . . . . . . . . . . . . . . . . . . . . . .

26

Utiliser une fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

26

La fonction type . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

27

La fonction print . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

28

4 Les structures conditionnelles

vi

31

Vos premires conditions et blocs dinstructions . . . . . . . . . . . . . . . . .

32

Forme minimale en if . . . . . . . . . . . . . . . . . . . . . . . . . . . .

32

Forme complte (if, elif et else) . . . . . . . . . . . . . . . . . . . . .

33

De nouveaux oprateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

36

Les oprateurs de comparaison . . . . . . . . . . . . . . . . . . . . . . .

36

Prdicats et boolens . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

36

Les mots-cls and, or et not . . . . . . . . . . . . . . . . . . . . . . . . .

37

Votre premier programme ! . . . . . . . . . . . . . . . . . . . . . . . . . . . .

38

Avant de commencer . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39

Sujet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39

Solution ou rsolution . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39

Correction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

41

TABLE DES MATIRES


5 Les boucles

45

En quoi cela consiste-t-il ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

46

La boucle while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

47

La boucle for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

49

Un petit bonus : les mots-cls break et continue . . . . . . . . . . . . . . . .

51

Le mot-cl break . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

51

Le mot-cl continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

51

6 Pas pas vers la modularit (1/2)

53

Les fonctions : vous de jouer . . . . . . . . . . . . . . . . . . . . . . . . . .

54

La cration de fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . .

54

Valeurs par dfaut des paramtres . . . . . . . . . . . . . . . . . . . . .

56

Signature dune fonction . . . . . . . . . . . . . . . . . . . . . . . . . . .

57

Linstruction return . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

58

Les fonctions lambda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

59

Syntaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

59

Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

la dcouverte des modules

. . . . . . . . . . . . . . . . . . . . . . . . . . .

60

Les modules, quest-ce que cest ? . . . . . . . . . . . . . . . . . . . . . .

60

La mthode import . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

Utiliser un espace de noms spcifique . . . . . . . . . . . . . . . . . . . .

62

Une autre mthode dimportation : from ... import ... . . . . . . . .

63

Bilan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

64

7 Pas pas vers la modularit (2/2)

67

Mettre en bote notre code . . . . . . . . . . . . . . . . . . . . . . . . . . . .

68

Fini, linterprteur ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

68

Emprisonnons notre programme dans un fichier . . . . . . . . . . . . . .

68

Quelques ajustements . . . . . . . . . . . . . . . . . . . . . . . . . . . .

70

Je viens pour conqurir le monde. . . et crer mes propres modules . . . . . . .

71

Mes modules moi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

71

Faire un test de module dans le module-mme . . . . . . . . . . . . . . .

73

Les packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

74

En thorie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

74

En pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

75
vii

TABLE DES MATIRES


8 Les exceptions
quoi cela sert-il ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

80

Forme minimale du bloc try . . . . . . . . . . . . . . . . . . . . . . . . . . .

81

Forme plus complte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

82

Excuter le bloc except pour un type dexception prcis . . . . . . . . .

82

Les mots-cls else et finally . . . . . . . . . . . . . . . . . . . . . . .

84

Un petit bonus : le mot-cl pass . . . . . . . . . . . . . . . . . . . . . .

85

Les assertions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

85

Lever une exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

86

9 TP : tous au ZCasino

II

79

89

Notre sujet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

90

Notre rgle du jeu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

90

Organisons notre projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

90

Le module random . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

91

Arrondir un nombre . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

91

vous de jouer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

91

Correction ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

92

Et maintenant ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

94

La Programmation Oriente Objet ct utilisateur

10 Notre premier objet : les chanes de caractres

95
97

Vous avez dit objet ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

98

Les mthodes de la classe str . . . . . . . . . . . . . . . . . . . . . . . . . . .

98

Mettre en forme une chane . . . . . . . . . . . . . . . . . . . . . . . . . 100


Formater et afficher une chane . . . . . . . . . . . . . . . . . . . . . . . 101
Parcours et slection de chanes . . . . . . . . . . . . . . . . . . . . . . . . . . 105
Parcours par indice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
Slection de chanes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
11 Les listes et tuples (1/2)

109

Crons et ditons nos premires listes . . . . . . . . . . . . . . . . . . . . . . 110


Dabord cest quoi, une liste ? . . . . . . . . . . . . . . . . . . . . . . . . 110
Cration de listes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
viii

TABLE DES MATIRES


Insrer des objets dans une liste . . . . . . . . . . . . . . . . . . . . . . . 111
Suppression dlments dune liste . . . . . . . . . . . . . . . . . . . . . 113
Le parcours de listes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
La fonction enumerate . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Un petit coup dil aux tuples . . . . . . . . . . . . . . . . . . . . . . . . . . 118
Affectation multiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
Une fonction renvoyant plusieurs valeurs . . . . . . . . . . . . . . . . . . 119
12 Les listes et tuples (2/2)

121

Entre chanes et listes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122


Des chanes aux listes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
Des listes aux chanes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
Une application pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
Les listes et paramtres de fonctions . . . . . . . . . . . . . . . . . . . . . . . 124
Les fonctions dont on ne connat pas lavance le nombre de paramtres 124
Transformer une liste en paramtres de fonction . . . . . . . . . . . . . . 127
Les comprhensions de liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
Parcours simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
Filtrage avec un branchement conditionnel . . . . . . . . . . . . . . . . . 128
Mlangeons un peu tout cela . . . . . . . . . . . . . . . . . . . . . . . . 128
Nouvelle application concrte . . . . . . . . . . . . . . . . . . . . . . . . 129
13 Les dictionnaires

133

Cration et dition de dictionnaires . . . . . . . . . . . . . . . . . . . . . . . . 134


Crer un dictionnaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
Supprimer des cls dun dictionnaire . . . . . . . . . . . . . . . . . . . . 137
Un peu plus loin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
Les mthodes de parcours . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Parcours des cls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Parcours des valeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Parcours des cls et valeurs simultanment . . . . . . . . . . . . . . . . . 140
Les dictionnaires et paramtres de fonction . . . . . . . . . . . . . . . . . . . 141
Rcuprer les paramtres nomms dans un dictionnaire . . . . . . . . . 141
Transformer un dictionnaire en paramtres nomms dune fonction . . . 142
ix

TABLE DES MATIRES


14 Les fichiers

145

Avant de commencer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146


Mais dabord, pourquoi lire ou crire dans des fichiers ?

. . . . . . . . . 146

Changer le rpertoire de travail courant . . . . . . . . . . . . . . . . . . 146


Chemins relatifs et absolus

. . . . . . . . . . . . . . . . . . . . . . . . . 147

Lecture et criture dans un fichier . . . . . . . . . . . . . . . . . . . . . . . . 148


Ouverture du fichier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
Fermer le fichier

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

Lire lintgralit du fichier . . . . . . . . . . . . . . . . . . . . . . . . . . 150


criture dans un fichier . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
crire dautres types de donnes . . . . . . . . . . . . . . . . . . . . . . 151
Le mot-cl with . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
Enregistrer des objets dans des fichiers . . . . . . . . . . . . . . . . . . . . . . 152
Enregistrer un objet dans un fichier

. . . . . . . . . . . . . . . . . . . . 152

Rcuprer nos objets enregistrs . . . . . . . . . . . . . . . . . . . . . . 153


15 Porte des variables et rfrences

155

La porte des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156


Dans nos fonctions, quelles variables sont accessibles ? . . . . . . . . . . 156
La porte de nos variables . . . . . . . . . . . . . . . . . . . . . . . . . . 157
Les variables globales

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161

Le principe des variables globales . . . . . . . . . . . . . . . . . . . . . . 161


Utiliser concrtement les variables globales . . . . . . . . . . . . . . . . . 162
16 TP : un bon vieux pendu

163

Votre mission . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164


Un jeu du pendu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
Le ct technique du problme . . . . . . . . . . . . . . . . . . . . . . . 164
Grer les scores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
vous de jouer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
Correction propose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
donnees.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
fonctions.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
pendu.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
Rsum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
x

TABLE DES MATIRES

III

La Programmation Oriente Objet ct dveloppeur

17 Premire approche des classes

171
173

Les classes, tout un monde . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174


Pourquoi utiliser des objets ? . . . . . . . . . . . . . . . . . . . . . . . . 174
Choix du modle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
Convention de nommage . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
Nos premiers attributs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
Quand on cre notre objet. . . . . . . . . . . . . . . . . . . . . . . . . . . 177
toffons un peu notre constructeur . . . . . . . . . . . . . . . . . . . . . 177
Attributs de classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
Les mthodes, la recette . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
Le paramtre self . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
Mthodes de classe et mthodes statiques . . . . . . . . . . . . . . . . . 183
Un peu dintrospection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
La fonction dir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
Lattribut spcial __dict__ . . . . . . . . . . . . . . . . . . . . . . . . . 187
18 Les proprits

189

Quest-ce que lencapsulation ? . . . . . . . . . . . . . . . . . . . . . . . . . . 190


Les proprits la casserole . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
Les proprits en action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
Rsumons le principe dencapsulation en Python . . . . . . . . . . . . . 194
19 Les mthodes spciales

195

dition de lobjet et accs aux attributs . . . . . . . . . . . . . . . . . . . . . 196


dition de lobjet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
Reprsentation de lobjet . . . . . . . . . . . . . . . . . . . . . . . . . . 197
Accs aux attributs de notre objet . . . . . . . . . . . . . . . . . . . . . 199
Les mthodes de conteneur . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
Accs aux lments dun conteneur . . . . . . . . . . . . . . . . . . . . . 202
La mthode spciale derrire le mot-cl in . . . . . . . . . . . . . . . . . 203
Connatre la taille dun conteneur . . . . . . . . . . . . . . . . . . . . . . 203
Les mthodes mathmatiques . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
Ce quil faut savoir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
xi

TABLE DES MATIRES


Tout dpend du sens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
Dautres oprateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
Les mthodes de comparaison . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
Des mthodes spciales utiles pickle . . . . . . . . . . . . . . . . . . . . . . 208
La mthode spciale __getstate__ . . . . . . . . . . . . . . . . . . . . . 208
La mthode __setstate__ . . . . . . . . . . . . . . . . . . . . . . . . . 209
On peut enregistrer dans un fichier autre chose que des dictionnaires . . 210
Je veux encore plus puissant ! . . . . . . . . . . . . . . . . . . . . . . . . 210
20 Parenthse sur le tri en Python

213

Premire approche du tri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214


Deux mthodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
Aperu des critres de tri . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Trier avec des cls prcises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Largument key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
Trier une liste dobjets . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
Trier dans lordre inverse . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
Plus rapide et plus efficace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
Les fonctions du module operator . . . . . . . . . . . . . . . . . . . . . . 221
Trier selon plusieurs critres . . . . . . . . . . . . . . . . . . . . . . . . . 222
En rsum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
21 Lhritage

227

Pour bien commencer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228


Lhritage simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
Petite prcision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
Deux fonctions trs pratiques . . . . . . . . . . . . . . . . . . . . . . . . 232
Lhritage multiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
Recherche des mthodes . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
Retour sur les exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
Cration dexceptions personnalises . . . . . . . . . . . . . . . . . . . . 235
22 Derrire la boucle for

239

Les itrateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240


Utiliser les itrateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
xii

TABLE DES MATIRES


Crons nos itrateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
Les gnrateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
Les gnrateurs simples . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
Les gnrateurs comme co-routines . . . . . . . . . . . . . . . . . . . . . 245
23 TP : un dictionnaire ordonn

249

Notre mission . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250


Spcifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
Exemple de manipulation . . . . . . . . . . . . . . . . . . . . . . . . . . 251
Tous au dpart !

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252

Correction propose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252


Le mot de la fin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
24 Les dcorateurs

257

Quest-ce que cest ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258


En thorie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
Format le plus simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
Modifier le comportement de notre fonction . . . . . . . . . . . . . . . . 260
Un dcorateur avec des paramtres . . . . . . . . . . . . . . . . . . . . . 263
Tenir compte des paramtres de notre fonction . . . . . . . . . . . . . . 266
Des dcorateurs sappliquant aux dfinitions de classes . . . . . . . . . . 267
Chaner nos dcorateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
Exemples dapplications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
Les classes singleton . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
Contrler les types passs notre fonction . . . . . . . . . . . . . . . . . 269
25 Les mtaclasses

273

Retour sur le processus dinstanciation . . . . . . . . . . . . . . . . . . . . . . 274


La mthode __new__ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
Crer une classe dynamiquement . . . . . . . . . . . . . . . . . . . . . . . . . 276
La mthode que nous connaissons . . . . . . . . . . . . . . . . . . . . . . 276
Crer une classe dynamiquement . . . . . . . . . . . . . . . . . . . . . . 277
Dfinition dune mtaclasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
La mthode __new__ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
La mthode __init__ . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
xiii

TABLE DES MATIRES


Les mtaclasses en action . . . . . . . . . . . . . . . . . . . . . . . . . . 281
Pour conclure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282

IV

Les merveilles de la bibliothque standard

26 Les expressions rgulires

285
287

Que sont les expressions rgulires ? . . . . . . . . . . . . . . . . . . . . . . . 288


Quelques lments de syntaxe pour les expressions rgulires . . . . . . . 288
Concrtement, comment cela se prsente-t-il ? . . . . . . . . . . . . . . . 288
Des caractres ordinaires . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
Rechercher au dbut ou la fin de la chane . . . . . . . . . . . . . . . . 289
Contrler le nombre doccurences . . . . . . . . . . . . . . . . . . . . . . 289
Les classes de caractres . . . . . . . . . . . . . . . . . . . . . . . . . . . 290
Les groupes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290
Le module re . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
Chercher dans une chane . . . . . . . . . . . . . . . . . . . . . . . . . . 291
Remplacer une expression . . . . . . . . . . . . . . . . . . . . . . . . . . 293
Des expressions compiles . . . . . . . . . . . . . . . . . . . . . . . . . . 295
27 Le temps

297

Le module time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298


Reprsenter une date et une heure dans un nombre unique . . . . . . . . 298
La date et lheure de faon plus prsentable . . . . . . . . . . . . . . . . 299
Rcuprer un timestamp depuis une date . . . . . . . . . . . . . . . . . 300
Mettre en pause lexcution du programme pendant un temps dtermin 301
Formater un temps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
Bien dautres fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
Le module datetime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
Reprsenter une date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
Reprsenter une heure . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304
Reprsenter des dates et heures . . . . . . . . . . . . . . . . . . . . . . . 304
28 Un peu de programmation systme

307

Les flux standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308


Accder aux flux standard . . . . . . . . . . . . . . . . . . . . . . . . . . 308
xiv

TABLE DES MATIRES


Modifier les flux standard . . . . . . . . . . . . . . . . . . . . . . . . . . 309
Les signaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
Les diffrents signaux

. . . . . . . . . . . . . . . . . . . . . . . . . . . . 310

Intercepter un signal . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311


Interprter les arguments de la ligne de commande . . . . . . . . . . . . . . . 313
Accder la console de Windows . . . . . . . . . . . . . . . . . . . . . . 313
Accder aux arguments de la ligne de commande . . . . . . . . . . . . . 314
Interprter les arguments de la ligne de commande . . . . . . . . . . . . 315
Excuter une commande systme depuis Python . . . . . . . . . . . . . . . . 320
La fonction system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320
La fonction popen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
29 Un peu de mathmatiques

323

Pour commencer, le module math . . . . . . . . . . . . . . . . . . . . . . . . . 324


Fonctions usuelles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
Un peu de trigonomtrie . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
Arrondir un nombre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
Des fractions avec le module fractions . . . . . . . . . . . . . . . . . . . . . 325
Crer une fraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
Manipuler les fractions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
Du pseudo-alatoire avec random . . . . . . . . . . . . . . . . . . . . . . . . . 327
Du pseudo-alatoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
La fonction random . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
randrange et randint . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328
Oprations sur des squences . . . . . . . . . . . . . . . . . . . . . . . . 328
30 Gestion des mots de passe

331

Rceptionner un mot de passe saisi par lutilisateur . . . . . . . . . . . . . . . 332


Chiffrer un mot de passe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
Chiffrer un mot de passe ? . . . . . . . . . . . . . . . . . . . . . . . . . . 333
Chiffrer un mot de passe . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
31 Le rseau

337

Brve prsentation du rseau . . . . . . . . . . . . . . . . . . . . . . . . . . . 338


Le protocole TCP

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
xv

TABLE DES MATIRES


Clients et serveur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
Les diffrentes tapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
tablir une connexion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
Les sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
Les sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
Construire notre socket . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
Connecter le socket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
Faire couter notre socket . . . . . . . . . . . . . . . . . . . . . . . . . . 341
Accepter une connexion venant du client . . . . . . . . . . . . . . . . . . 341
Cration du client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
Connecter le client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
Faire communiquer nos sockets . . . . . . . . . . . . . . . . . . . . . . . 343
Fermer la connexion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
Le serveur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
Le client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
Un serveur plus labor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
Le module select . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
Et encore plus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
32 Les tests unitaires avec unittest

351

Pourquoi tester ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352


Premiers exemples de tests unitaires . . . . . . . . . . . . . . . . . . . . . . . 353
Tester une fonctionnalit existante . . . . . . . . . . . . . . . . . . . . . 354
Les principales mthodes dassertion . . . . . . . . . . . . . . . . . . . . 361
La dcouverte automatique des tests . . . . . . . . . . . . . . . . . . . . . . . 362
Lancement de tests unitaires depuis un rpertoire . . . . . . . . . . . . . 362
Structure dun projet avec ses tests . . . . . . . . . . . . . . . . . . . . . 364
En rsum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
33 La programmation parallle avec threading

365

Cration de threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366


Premier exemple dun thread . . . . . . . . . . . . . . . . . . . . . . . . 366
La synchronisation des threads . . . . . . . . . . . . . . . . . . . . . . . . . . 369
Oprations concurrentes . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
Accs simultane des ressources . . . . . . . . . . . . . . . . . . . . . . 370
xvi

TABLE DES MATIRES


Les locks la rescousse . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
En rsum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
34 Des interfaces graphiques avec Tkinter

375

Prsentation de Tkinter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376


Votre premire interface graphique . . . . . . . . . . . . . . . . . . . . . . . . 376
De nombreux widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
Les widgets les plus communs . . . . . . . . . . . . . . . . . . . . . . . . 378
Organiser ses widgets dans la fentre . . . . . . . . . . . . . . . . . . . . 381
Bien dautres widgets

. . . . . . . . . . . . . . . . . . . . . . . . . . . . 382

Les commandes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382


Pour conclure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384

Annexes

35 crire nos programmes Python dans des fichiers

385
387

Mettre le code dans un fichier . . . . . . . . . . . . . . . . . . . . . . . . . . . 388


Excuter notre code sur Windows . . . . . . . . . . . . . . . . . . . . . . 388
Sur les systmes Unix . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389
Prciser lencodage de travail . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
Mettre en pause notre programme . . . . . . . . . . . . . . . . . . . . . . . . 390
36 Distribuer facilement nos programmes Python avec cx_Freeze

393

En thorie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
Avantages de cx_Freeze . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
En pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
Utiliser le script cxfreeze . . . . . . . . . . . . . . . . . . . . . . . . . . 395
Le fichier setup.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
Pour conclure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398
37 De bonnes pratiques

399

Pourquoi suivre les conventions des PEP ? . . . . . . . . . . . . . . . . . . . . 400


La PEP 20 : tout une philosophie . . . . . . . . . . . . . . . . . . . . . . . . . 400
La PEP 8 : des conventions prcises . . . . . . . . . . . . . . . . . . . . . . . 402
xvii

TABLE DES MATIRES


Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402
Forme du code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402
Directives dimportation . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
Le signe espace dans les expressions et instructions . . . . . . . . . . . . 404
Commentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406
Conventions de nommage . . . . . . . . . . . . . . . . . . . . . . . . . . 406
Conventions de programmation . . . . . . . . . . . . . . . . . . . . . . . 407
Conclusion

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408

La PEP 257 : de belles documentations . . . . . . . . . . . . . . . . . . . . . 408


Quest-ce quune docstring ? . . . . . . . . . . . . . . . . . . . . . . . . . 408
Les docstrings sur une seule ligne . . . . . . . . . . . . . . . . . . . . . . 409
Les docstrings sur plusieurs lignes . . . . . . . . . . . . . . . . . . . . . . 410
38 Pour finir et bien continuer

413

Quelques rfrences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414


La documentation officielle . . . . . . . . . . . . . . . . . . . . . . . . . 414
Le wiki Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414
Lindex des PEP (Python Enhancement Proposal) . . . . . . . . . . . . 415
La documentation par version . . . . . . . . . . . . . . . . . . . . . . . . 415
Des bibliothques tierces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416
Pour crer une interface graphique . . . . . . . . . . . . . . . . . . . . . 416
Dans le monde du Web

. . . . . . . . . . . . . . . . . . . . . . . . . . . 417

Un peu de rseau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418


Pour conclure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418

xviii

Premire partie

Introduction Python

Chapitre

Quest-ce que Python ?


Difficult :

ous avez dcid dapprendre le Python et je ne peux que vous en fliciter. Jessaierai
danticiper vos questions et de ne laisser personne en arrire.

Dans ce chapitre, je vais dabord vous expliquer ce quest un langage de programmation.


Nous verrons ensuite brivement lhistoire de Python, afin que vous sachiez au moins do
vient ce langage ! Ce chapitre est thorique mais je vous conseille vivement de le lire quand
mme.
La dernire section portera sur linstallation de Python, une tape essentielle pour continuer
ce cours. Que vous travailliez avec Windows, Linux ou Mac OS X, vous y trouverez des
explications prcises sur linstallation.
Allez, on attaque !

CHAPITRE 1. QUEST-CE QUE PYTHON ?

Un langage de programmation ? Quest-ce que cest ?


La communication humaine
Non, ceci nest pas une explication biologique ou philosophique, ne partez pas ! Trs
simplement, si vous arrivez comprendre ces suites de symboles tranges et dconcertants que sont les lettres de lalphabet, cest parce que nous respectons certaines
conventions, dans le langage et dans lcriture. En franais, il y a des rgles de grammaire et dorthographe, je ne vous apprends rien. Vous communiquez en connaissant
plus ou moins consciemment ces rgles et en les appliquant plus ou moins bien, selon
les cas. Cependant, ces rgles peuvent tre aisment contournes : personne ne peut
prtendre connatre lensemble des rgles de la grammaire et de lorthographe franaises, et peu de gens sen soucient. Aprs tout, mme si vous faites des fautes, les
personnes avec qui vous communiquez pourront facilement vous comprendre. Quand
on communique avec un ordinateur, cependant, cest trs diffrent.

Mon ordinateur communique aussi !


Eh oui, votre ordinateur communique sans cesse avec vous et vous communiquez sans
cesse avec lui. Daccord, il vous dit trs rarement quil a faim, que lt sannonce
caniculaire et que le dernier disque de ce groupe trs connu tait pleurer. Il ny a rien
de magique si, quand vous cliquez sur la petite croix en haut droite de lapplication
en cours, celle-ci comprend quelle doit se fermer.
Le langage machine
En fait, votre ordinateur se fonde aussi sur un langage pour communiquer avec vous
ou avec lui-mme. Les oprations quun ordinateur peut effectuer la base sont des
plus classiques et constitues de laddition de deux nombres, leur soustraction, leur
multiplication, leur division, entire ou non. Et pourtant, ces cinq oprations suffisent
amplement faire fonctionner les logiciels de simulation les plus complexes ou les jeux
super-ralistes. Tous ces logiciels fonctionnent en gros de la mme faon :
une suite dinstructions crites en langage machine compose le programme ;
lors de lexcution du programme, ces instructions dcrivent lordinateur ce quil
faut faire (lordinateur ne peut pas le deviner).

Une liste dinstructions ? Quest-ce que cest encore que cela ?

En schmatisant volontairement, une instruction pourrait demander au programme de


se fermer si vous cliquez sur la croix en haut droite de votre cran, ou de rester en
tche de fond si tel est son bon plaisir. Toutefois, en langage machine, une telle action
demande elle seule un nombre assez important dinstructions. Mais bon, vous pouvez
4

POUR LA PETITE HISTOIRE


vous en douter, parler avec lordinateur en langage machine, qui ne comprend que le
binaire, ce nest ni trs enrichissant, ni trs pratique, et en tous cas pas trs marrant.
On a donc invent des langages de programmation pour faciliter la communication avec
lordinateur.
Le langage binaire est uniquement constitu de 0 et de 1.
01000010011011110110111001101010011011110111010101110010 ,
par exemple, signifie Bonjour . Bref, autant vous dire que discuter en
binaire avec un ordinateur peut tre long (surtout pour vous).

Les langages de programmation


Les langages de programmation sont des langages bien plus faciles comprendre pour
nous, pauvres tres humains que nous sommes. Le mcanisme reste le mme, mais le
langage est bien plus comprhensible. Au lieu dcrire les instructions dans une suite
assez peu intelligible de 0 et de 1, les ordres donns lordinateur sont crits dans un
langage , souvent en anglais, avec une syntaxe particulire quil est ncessaire de
respecter. Mais avant que lordinateur puisse comprendre ce langage, celui-ci doit tre
traduit en langage machine (figure 1.1).

Figure 1.1 Traduction dun programme en langage binaire


En gros, le programmeur na qu crire des lignes de code dans le langage quil
a choisi, les tapes suivantes sont automatises pour permettre lordinateur de les
dcoder.
Il existe un grand nombre de langages de programmation et Python en fait partie. Il
nest pas ncessaire pour le moment de donner plus dexplications sur ces mcanismes
trs schmatiss. Si vous navez pas russi comprendre les mots de vocabulaire et
lensemble de ces explications, cela ne vous pnalisera pas pour la suite. Mais je trouvais intressant de donner ces prcisions quant aux faons de communiquer avec son
ordinateur.

Pour la petite histoire


Python est un langage de programmation, dont la premire version est sortie en 1991.
Cr par Guido van Rossum, il a voyag du Macintosh de son crateur, qui travaillait
5

CHAPITRE 1. QUEST-CE QUE PYTHON ?


cette poque au Centrum voor Wiskunde en Informatica aux Pays-Bas, jusqu se
voir associer une organisation but non lucratif particulirement dvoue, la Python
Software Foundation, cre en 2001. Ce langage a t baptis ainsi en hommage
la troupe de comiques les Monty Python .

quoi peut servir Python ?


Python est un langage puissant, la fois facile apprendre et riche en possibilits.
Ds linstant o vous linstallez sur votre ordinateur, vous disposez de nombreuses
fonctionnalits intgres au langage que nous allons dcouvrir tout au long de ce livre.
Il est, en outre, trs facile dtendre les fonctionnalits existantes, comme nous allons le
voir. Ainsi, il existe ce quon appelle des bibliothques qui aident le dveloppeur travailler sur des projets particuliers. Plusieurs bibliothques peuvent ainsi tre installes
pour, par exemple, dvelopper des interfaces graphiques en Python.
Concrtement, voil ce quon peut faire avec Python :
de petits programmes trs simples, appels scripts, chargs dune mission trs prcise
sur votre ordinateur ;
des programmes complets, comme des jeux, des suites bureautiques, des logiciels
multimdias, des clients de messagerie. . .
des projets trs complexes, comme des progiciels (ensemble de plusieurs logiciels
pouvant fonctionner ensemble, principalement utiliss dans le monde professionnel).
Voici quelques-unes des fonctionnalits offertes par Python et ses bibliothques :

crer des interfaces graphiques ;


faire circuler des informations au travers dun rseau ;
dialoguer dune faon avance avec votre systme dexploitation ;
. . . et jen passe. . .

Bien entendu, vous nallez pas apprendre faire tout cela en quelques minutes. Mais
ce cours vous donnera des bases suffisamment larges pour dvelopper des projets qui
pourront devenir, par la suite, assez importants.

Un langage de programmation interprt


Eh oui, vous allez devoir patienter encore un peu car il me reste deux ou trois choses
vous expliquer, et je suis persuad quil est important de connatre un minimum
ces dtails qui peuvent sembler peu pratiques de prime abord. Python est un langage
de programmation interprt, cest--dire que les instructions que vous lui envoyez
sont transcrites en langage machine au fur et mesure de leur lecture. Dautres
langages (comme le C / C++) sont appels langages compils car, avant de pouvoir
les excuter, un logiciel spcialis se charge de transformer le code du programme en
langage machine. On appelle cette tape la compilation . chaque modification
du code, il faut rappeler une tape de compilation.
Les avantages dun langage interprt sont la simplicit (on ne passe pas par une tape
6

INSTALLER PYTHON
de compilation avant dexcuter son programme) et la portabilit (un langage tel que
Python est cens fonctionner aussi bien sous Windows que sous Linux ou Mac OS, et on
ne devrait avoir effectuer aucun changement dans le code pour le passer dun systme
lautre). Cela ne veut pas dire que les langages compils ne sont pas portables, loin de
l ! Mais on doit utiliser des compilateurs diffrents et, dun systme lautre, certaines
instructions ne sont pas compatibles, voire se comportent diffremment.
En contrepartie, un langage compil se rvlera bien plus rapide quun langage interprt (la traduction la vole de votre programme ralentit lexcution), bien que
cette diffrence tende se faire de moins en moins sentir au fil des amliorations. De
plus, il faudra installer Python sur le systme dexploitation que vous utilisez pour que
lordinateur puisse comprendre votre code.

Diffrentes versions de Python


Lors de la cration de la Python Software Foundation, en 2001, et durant les annes
qui ont suivi, le langage Python est pass par une suite de versions que lon a englobes
dans lappellation Python 2.x (2.3, 2.5, 2.6. . .). Depuis le 13 fvrier 2009, la version
3.0.1 est disponible. Cette version casse la compatibilit ascendante qui prvalait
lors des dernires versions.
Compatibilit quoi ?

Quand un langage de programmation est mis jour, les dveloppeurs se gardent bien
de supprimer ou de trop modifier danciennes fonctionnalits. Lintrt est quun programme qui fonctionne sous une certaine version marchera toujours avec la nouvelle
version en date. Cependant, la Python Software Foundation, observant un bon nombre
de fonctionnalits obsoltes, mises en uvre plusieurs fois. . . a dcid de nettoyer tout
le projet. Un programme qui tourne la perfection sous Python 2.x devra donc tre
mis jour un minimum pour fonctionner de nouveau sous Python 3. Cest pourquoi je
vais vous conseiller ultrieurement de tlcharger et dinstaller la dernire version en
date de Python. Je mattarderai en effet sur les fonctionnalits de Python 3 et certaines
dentre elles ne seront pas accessibles (ou pas sous le mme nom) dans les anciennes
versions.
Ceci tant pos, tous linstallation !

Installer Python
Linstallation de Python est un jeu denfant, aussi bien sous Windows que sous les
systmes Unix. Quel que soit votre systme dexploitation, vous devez vous rendre sur
le site officiel de Python. Pour cela, utilisez le code web suivant :
7

CHAPITRE 1. QUEST-CE QUE PYTHON ?



Site officiel de Python
B
Code web : 199501

Sous Windows
1. Cliquez sur le lien Download dans le menu principal de la page.
2. Slectionnez la version de Python que vous souhaitez utiliser (je vous conseille la
dernire en date).
3. On vous propose un (ou plusieurs) lien(s) vers une version Windows : slectionnez celle qui conviendra votre processeur. Si vous avez un doute, tlchargez
une version x86 . Si votre ordinateur vous signale quil ne peut excuter le
programme, essayez une autre version de Python.
4. Enregistrez puis excutez le fichier dinstallation et suivez les tapes. Ce nest ni
trs long ni trs difficile.
5. Une fois linstallation termine, vous pouvez vous rendre dans le menu Dmarrer
> Tous les programmes. Python devrait apparatre dans cette liste (figure 1.2).
Nous verrons bientt comment le lancer, pas dimpatience. . .

Figure 1.2 Python est install sous Windows

Sous Linux
Python est pr-install sur la plupart des distributions Linux. Cependant, il est possible que vous nayez pas la dernire version en date. Pour le vrifier, tapez dans un
terminal la commande python -V. Cette commande vous renvoie la version de Python
actuellement installe sur votre systme. Il est trs probable que ce soit une version
2.x, comme 2.6 ou 2.7, pour des raisons de compatibilit. Dans tous les cas, je vous
conseille dinstaller Python 3.x, la syntaxe est trs proche de Python 2.x mais diffre
quand mme. . .
8

INSTALLER PYTHON
Cliquez sur download et tlchargez la dernire version de Python (actuellement Python 3.4 gzipped source tarball (for Linux, Unix or OS X) ). Ouvrez un terminal, puis
rendez-vous dans le dossier o se trouve larchive :
1. Dcompressez larchive en tapant : tar -xzf Python-3.4.0.tar.bz2 (cette commande est bien entendu adapter suivant la version et le type de compression).
2. Attendez quelques instants que la dcompression se termine, puis rendez-vous
dans le dossier qui vient dtre cr dans le rpertoire courant (Python-3.4.0
dans mon cas).
3. Excutez le script configure en tapant ./configure dans la console.
4. Une fois que la configuration sest droule, il ny a plus qu compiler en tapant
make puis make install en tant que super-utilisateur.

Sous Mac OS X
Tlchargez la dernire version de Python. Ouvrez le fichier .dmg et faites un double-clic
sur le paquet dinstallation Python.mpkg
Un assistant dinstallation souvre, laissez-vous guider : Python est maintenant install !

Lancer Python
Ouf ! Voil qui est fait !
Bon, en thorie, on commence utiliser Python ds le prochain chapitre mais, pour
que vous soyez un peu rcompenss de votre installation exemplaire, voici les diffrents
moyens daccder la ligne de commande Python que nous allons tout particulirement
tudier dans les prochains chapitres.
Sous Windows
Vous avez plusieurs faons daccder la ligne de commande Python, la plus vidente
consistant passer par les menus Dmarrer > Tous les programmes > Python 3.4
> Python (Command Line). Si tout se passe bien, vous devriez obtenir une magnifique
console (figure 1.3). Il se peut que les informations affiches dans la vtre ne soient pas
les mmes, mais ne vous en inquitez pas.
Quest-ce que cest que cela ?

On verra plus tard. Limportant, cest que vous ayez russi ouvrir la console dinterprtation de Python, le reste attendra le prochain chapitre.
Vous pouvez galement passer par la ligne de commande Windows ; cause des raccourcis, je privilgie en gnral cette mthode, mais cest une question de got. Allez
9

CHAPITRE 1. QUEST-CE QUE PYTHON ?

Figure 1.3 La console Python sous Windows

dans le menu Dmarrer, puis cliquez sur Excuter. Dans la fentre qui saffiche, tapez
simplement python et la ligne de commande Python devrait safficher de nouveau.
Sachez
que vous

 pouvez directement vous rendre dans Excuter en tapant le raccourci
Windows
+

 R .
Pour fermer linterprteur
de commandes Python, vous pouvez tapez exit() puis

appuyer sur la touche Entre .

Sous Linux
Lorsque vous lavez install sur votre systme, Python a cr un lien vers linterprteur
sous la forme python3.X (le X tant le numro de la version installe).
Si, par exemple, vous avez install Python 3.4, vous pouvez y accder grce la commande :
1
2
3
4
5

$ python3 .4
Python 3.4.0 ( default , Apr 23 2014 , 05:55:41)
[ GCC 4.4.5] on linux
Type " help " , " copyright " , " credits " or " license " for more
information .
>>>




Pour
fermer la ligne de commande Python, nutilisez pas CTRL + C mais CTRL +

D (nous verrons plus tard pourquoi).
10

INSTALLER PYTHON
Sous Mac OS X
Cherchez un dossier Python dans le dossier Applications. Pour lancer Python, ouvrez
lapplication IDLE de ce dossier. Vous tes prts passer au concret !

En rsum
Python est un langage de programmation interprt, ne pas confondre avec un
langage compil.
Il permet de crer toutes sortes de programmes, comme des jeux, des logiciels, des
progiciels, etc.
Il est possible dassocier des bibliothques Python afin dtendre ses possibilits.
Il est portable, cest dire quil peut fonctionner sous diffrents systmes dexploitation (Windows, Linux, Mac OS X,. . .).

11

CHAPITRE 1. QUEST-CE QUE PYTHON ?

12

Chapitre

Premiers pas avec linterprteur de


commandes Python
Difficult :
prs les premires notions thoriques et linstallation de Python, il est temps de
dcouvrir un peu linterprteur de commandes de ce langage. Mme si ces petits tests
vous semblent anodins, vous dcouvrirez dans ce chapitre les premiers rudiments de
la syntaxe du langage et je vous conseille fortement de me suivre pas pas, surtout si vous
tes face votre premier langage de programmation.

Comme tout langage de programmation, Python a une syntaxe claire : on ne peut pas lui
envoyer nimporte quelle information dans nimporte quel ordre. Nous allons voir ici ce que
Python mange. . . et ce quil ne mange pas.

13

CHAPITRE 2. PREMIERS PAS AVEC LINTERPRTEUR DE COMMANDES


PYTHON

O est-ce quon est, l ?


Pour commencer, je vais vous demander de retourner dans linterprteur de commandes
Python (je vous ai montr, la fin du chapitre prcdent, comment y accder en fonction
de votre systme dexploitation).
Je vous rappelle les informations qui figurent dans cette fentre, mme si elles peuvent
tre diffrentes chez vous en fonction de votre version et de votre systme dexploitation.
1
2
3

Python 3.4.0 ( v3 .4.0:04 f714765c13 , Mar 16 2014 , 19:24:06) [ MSC


v .1600 32 bit ( Intel ) ] on win 32
Type " help " , " copyright " , " credits " or " license " for more
information .
>>>

sa faon, Python vous souhaite la bienvenue dans son interprteur de commandes.


Attends, attends. Cest quoi cet interprteur ?

Souvenez-vous, au chapitre prcdent, je vous ai donn une brve explication sur la


diffrence entre langages compils et langages interprts. Eh bien, cet interprteur de
commandes va nous permettre de tester directement du code. Je saisis une ligne dinstructions, jappuie sur la touche Entre de mon clavier, je regarde ce que me rpond
Python (sil me dit quelque chose), puis jen saisis une deuxime, une troisime. . . Cet
interprteur est particulirement utile pour comprendre les bases de Python et raliser
nos premiers petits programmes. Le principal inconvnient, cest que le code que vous
saisissez nest pas sauvegard (sauf si vous lenregistrez manuellement, mais chaque
chose en son temps).
Dans la fentre que vous avez sous les yeux, linformation qui ne change pas dun
systme dexploitation lautre est la srie de trois chevrons qui se trouve en bas
gauche des informations : >>>. Ces trois signes signifient : je suis prt recevoir tes
instructions .
Comme je lai dit, les langages de programmation respectent une syntaxe claire. Vous ne
pouvez pas esprer que lordinateur comprenne si, dans cette fentre, vous commencez
par lui demander : jaimerais que tu me codes un jeu vido gnial . Et autant que
vous le sachiez tout de suite (bien qu mon avis, vous vous en doutiez), on est trs
loin dobtenir des rsultats aussi spectaculaires notre niveau.
Tout cela pour dire que, si vous saisissez nimporte quoi dans cette fentre, la probabilit
est grande que Python vous indique, clairement et fermement, quil na rien compris.
Si, par exemple, vous saisissez premier test avec Python , vous obtenez le rsultat
suivant :
1
2

14

>>> premier test avec Python


File " < stdin >" , line 1

VOS PREMIRES INSTRUCTIONS : UN PEU DE CALCUL MENTAL POUR


LORDINATEUR
3
4
5
6

premier test avec Python


^
SyntaxError : invalid syntax
>>>

Eh oui, linterprteur parle en anglais et les instructions que vous saisirez, comme
pour lcrasante majorit des langages de programmation, seront galement en anglais.
Mais pour linstant, rien de bien compliqu : linterprteur vous indique quil a trouv
un problme dans votre ligne dinstruction. Il vous indique le numro de la ligne (en
loccurence la premire), quil vous rpte obligeamment (ceci est trs utile quand on
travaille sur un programme de plusieurs centaines de lignes). Puis il vous dit ce qui
larrte, ici : SyntaxError: invalid syntax. Limpide nest-ce pas ? Ce que vous avez
saisi est incomprhensible pour Python. Enfin, la preuve quil nest pas rancunier, cest
quil vous affiche nouveau une srie de trois chevrons, montrant bien quil est prt
retenter laventure.
Bon, cest bien joli de recevoir un message derreur au premier test mais je me doute
que vous aimeriez bien voir des trucs qui fonctionnent, maintenant. Cest parti donc.

Vos premires instructions : un peu de calcul mental


pour lordinateur
Cest assez trivial, quand on y pense, mais je trouve quil sagit dune excellente manire daborder pas pas la syntaxe de Python. Nous allons donc essayer dobtenir les
rsultats de calculs plus ou moins compliqus. Je vous rappelle encore une fois quexcuter les tests en mme temps que moi sur votre machine est une trs bonne faon de
vous rendre compte de la syntaxe et surtout, de la retenir.

Saisir un nombre
Vous avez pu voir sur notre premier (et ce jour notre dernier) test que Python
naimait pas particulirement les suites de lettres quil ne comprend pas. Par contre,
linterprteur adore les nombres. Dailleurs, il les accepte sans sourciller, sans une seule
erreur :
1
2
3

>>> 7
7
>>>

Daccord, ce nest pas extraordinaire. On saisit un nombre et linterprteur le renvoie.


Mais dans bien des cas, ce simple retour indique que linterprteur a bien compris et
que votre saisie est en accord avec sa syntaxe. De mme, vous pouvez saisir des nombres
virgule.
1

>>> 9.5

15

CHAPITRE 2. PREMIERS PAS AVEC LINTERPRTEUR DE COMMANDES


PYTHON
2
3

9.5
>>>

Attention : on utilise ici la notation anglo-saxonne, cest--dire que le point


remplace la virgule. La virgule a un tout autre sens pour Python, prenez donc
cette habitude ds maintenant.
Il va de soi que lon peut tout aussi bien saisir des nombres ngatifs (vous pouvez
dailleurs faire lessai).

Oprations courantes
Bon, il est temps dapprendre utiliser les principaux oprateurs de Python, qui vont
vous servir pour la grande majorit de vos programmes.

Addition, soustraction, multiplication, division


Pour effectuer ces oprations, on utilise respectivement les symboles +, -, * et /.
1
2
3
4
5
6
7
8
9

>>> 3 + 4
7
>>> -2 + 93
91
>>> 9.5 + 2
11.5
>>> 3.11 + 2.08
5. 18 99 999 999999995
>>>

Pourquoi ce dernier rsultat approximatif ?

Python ny est pas pour grand chose. En fait, le problme vient en grande partie de la
faon dont les nombres virgule sont crits dans la mmoire de votre ordinateur. Cest
pourquoi, en programmation, on prfre travailler autant que possible avec des nombres
entiers. Cependant, vous remarquerez que lerreur est infime et quelle naura pas de rel
impact sur les calculs. Les applications qui ont besoin dune prcision mathmatique
toute preuve essayent de pallier ces dfauts par dautres moyens mais ici, ce ne sera
pas ncessaire.
Faites galement des tests pour la soustraction, la multiplication et la division : il ny
a rien de difficile.
16

VOS PREMIRES INSTRUCTIONS : UN PEU DE CALCUL MENTAL POUR


LORDINATEUR
Division entire et modulo
Si vous avez pris le temps de tester la division, vous vous tes rendu compte que le
rsultat est donn avec une virgule flottante.
1
2
3
4
5

>>> 10 / 5
2.0
>>> 10 / 3
3. 33 33 333 33 33 33335
>>>

Il existe deux autres oprateurs qui permettent de connatre le rsultat dune division
entire et le reste de cette division.
Le premier oprateur utilise le symbole // . Il permet dobtenir la partie entire
dune division.
1
2
3

>>> 10 // 3
3
>>>

Loprateur % , que lon appelle le modulo , permet de connatre le reste de la


division.
1
2
3

>>> 10%3
1
>>>

Ces notions de partie entire et de reste de division ne sont pas bien difficiles comprendre et vous serviront trs probablement par la suite.
Si vous avez du mal en saisir le sens, sachez donc que :
La partie entire de la division de 10 par 3 est le rsultat de cette division, sans tenir
compte des chiffres au-del de la virgule (en loccurence, 3).
Pour obtenir le modulo dune division, on rcupre son reste. Dans notre exemple,
10/3 = 3 et il reste 1. Une fois que lon a compris cela, ce nest pas bien compliqu.
Souvenez-vous bien de ces deux oprateurs, et surtout du modulo % , dont vous
aurez besoin dans vos programmes futurs.

En rsum
Linterprteur de commandes Python permet de tester du code au fur et mesure
quon lcrit.
Linterprteur Python accepte des nombres et est capable deffectuer des calculs.
Un nombre dcimal scrit avec un point et non une virgule.
Les calculs impliquant des nombres dcimaux donnent parfois des rsultats approximatifs, cest pourquoi on prfrera, dans la mesure du possible, travailler avec des
nombres entiers.
17

CHAPITRE 2. PREMIERS PAS AVEC LINTERPRTEUR DE COMMANDES


PYTHON

18

Chapitre

Le monde merveilleux des variables


Difficult :
u chapitre prcdent, vous avez saisi vos premires instructions en langage Python,
bien que vous ne vous en soyez peut-tre pas rendu compte. Il est galement vrai que
les instructions saisies auraient fonctionn dans la plupart des langages. Ici, cependant,
nous allons commencer approfondir un petit peu la syntaxe du langage, tout en dcouvrant
un concept important de la programmation : les variables.

Ce concept est essentiel et vous ne pouvez absolument pas faire limpasse dessus. Mais je
vous rassure, il ny a rien de compliqu, que de lutile et de lagrable.

19

CHAPITRE 3. LE MONDE MERVEILLEUX DES VARIABLES

Cest quoi, une variable ? Et quoi cela sert-il ?


Les variables sont lun des concepts qui se retrouvent dans la majorit (et mme, en
loccurrence, la totalit) des langages de programmation. Autant dire que sans variable,
on ne peut pas programmer, et ce nest pas une exagration.

Cest quoi, une variable ?


Une variable est une donne de votre programme, stocke dans votre ordinateur. Cest
un code alpha-numrique que vous allez lier une donne de votre programme, afin de
pouvoir lutiliser plusieurs reprises et faire des calculs un peu plus intressants avec.
Cest bien joli de savoir faire des oprations mais, si on ne peut pas stocker le rsultat
quelque part, cela devient trs vite ennuyeux.
Voyez la mmoire de votre ordinateur comme une grosse armoire avec plein de tiroirs.
Chaque tiroir peut contenir une donne ; certaines de ces donnes seront des variables
de votre programme.

Comment cela fonctionne-t-il ?


Le plus simplement du monde. Vous allez dire Python : je veux que, dans une
variable que je nomme age, tu stockes mon ge, pour que je puisse le retenir (si jai la
mmoire trs courte), laugmenter ( mon anniversaire) et lafficher si besoin est .
Comme je vous lai dit, on ne peut pas passer ct des variables. Vous ne voyez
peut-tre pas encore tout lintrt de stocker des informations de votre programme et
pourtant, si vous ne stockez rien, vous ne pouvez pratiquement rien faire.
En Python, pour donner une valeur une variable, il suffit dcrire nom_de_la_variable
= valeur.
Une variable doit respecter quelques rgles de syntaxe incontournables :
1. Le nom de la variable ne peut tre compos que de lettres, majuscules ou minuscules, de chiffres et du symbole soulign _ (appel underscore en anglais).
2. Le nom de la variable ne peut pas commencer par un chiffre.
3. Le langage Python est sensible la casse, ce qui signifie que des lettres majuscules
et minuscules ne constituent pas la mme variable (la variable AGE est diffrente
de aGe, elle-mme diffrente de age).
Au-del de ces rgles de syntaxe incontournables, il existe des conventions dfinies par
les programmeurs eux-mmes. Lune delle, que jai tendance utiliser assez souvent,
consiste crire la variable en minuscules et remplacer les espaces ventuels par un
espace soulign _ . Si je dois crer une variable contenant mon ge, elle se nommera
donc mon_age. Une autre convention utilise consiste passer en majuscule le premier
caractre de chaque mot, lexception du premier mot constituant la variable. La
variable contenant mon ge se nommerait alors monAge.
20

CEST QUOI, UNE VARIABLE ? ET QUOI CELA SERT-IL ?


Vous pouvez utiliser la convention qui vous plat, ou mme en crer une bien vous,
mais essayez de rester cohrent et de nutiliser quune seule convention dcriture. En
effet, il est essentiel de pouvoir vous reprer dans vos variables ds que vous commencez
travailler sur des programmes volumineux.
Ainsi, si je veux associer mon ge une variable, la syntaxe sera :
1

mon_age = 21

Linterprteur vous affiche aussitt trois chevrons sans aucun message. Cela signifie
quil a bien compris et quil ny a eu aucune erreur.
Sachez quon appelle cette tape laffectation de valeur une variable (parfois raccourci
en affectation de variable ). On dit en effet quon a affect la valeur 21 la variable
mon_age.
On peut afficher la valeur de cette variable en la saisissant simplement dans linterprteur de commandes.
1
2
3

>>> mon_age
21
>>>

Les espaces sparant = du nom et de la valeur de la variable sont facultatifs. Je les mets pour des raisons de lisibilit.

Bon, cest bien joli tout cela, mais quest-ce quon fait avec cette variable ?

Eh bien, tout ce que vous avez dj fait au chapitre prcdent, mais cette fois en
utilisant la variable comme un nombre part entire. Vous pouvez mme affecter
dautres variables des valeurs obtenues en effectuant des calculs sur la premire et cest
l toute la puissance de ce mcanisme.
Essayons par exemple daugmenter de 2 la variable mon_age.
1
2
3
4

>>> mon_age = mon_age + 2


>>> mon_age
23
>>>

Encore une fois, lors de laffectation de la valeur, rien ne saffiche, ce qui est parfaitement
normal.
Maintenant, essayons daffecter une valeur une autre variable daprs la valeur de
mon_age.
1

>>> mon_age_x2 = mon_age * 2

21

CHAPITRE 3. LE MONDE MERVEILLEUX DES VARIABLES


2
3
4

>>> mon_age_x2
46
>>>

Encore une fois, je vous invite tester en long, en large et en travers cette possibilit. Le
concept nest pas compliqu mais extrmement puissant. De plus, compar certains
langages, affecter une valeur une variable est extrmement simple. Si la variable nest
pas cre, Python sen charge automatiquement. Si la variable existe dj, lancienne
valeur est supprime et remplace par la nouvelle. Quoi de plus simple ?
Certains mots-cls de Python sont rservs, cest--dire que vous ne pouvez
pas crer des variables portant ce nom.
En voici la liste pour Python 3 :
and
as
assert
break
class
continue
def

del
elif
else
except
false
finally
for

from
global
if
import
in
is
lambda

none
nonlocal
not
or
pass
raise
return

true
try
while
with
yield

Ces mots-cls sont utiliss par Python, vous ne pouvez pas construire de variables
portant ces noms. Vous allez dcouvrir dans la suite de ce cours la majorit de ces
mots-cls et comment ils sutilisent.

Les types de donnes en Python


L se trouve un concept trs important, que lon retrouve dans beaucoup de langages
de programmation. Ouvrez grand vos oreilles, ou plutt vos yeux, car vous devrez tre
parfaitement laise avec ce concept pour continuer la lecture de ce livre. Rassurez-vous
toutefois, du moment que vous tes attentifs, il ny a rien de compliqu comprendre.

Quentend-on par type de donne ?


Jusquici, vous navez travaill quavec des nombres. Et, sil faut bien avouer quon
ne fera que trs rarement un programme sans aucun nombre, cest loin dtre la seule
donne que lon peut utiliser en Python. terme, vous serez mme capables de crer
vos propres types de donnes, mais nanticipons pas.
Python a besoin de connatre quels types de donnes sont utiliss pour savoir quelles
oprations il peut effectuer avec. Dans ce chapitre, vous allez apprendre travailler avec
22

LES TYPES DE DONNES EN PYTHON


des chanes de caractres, et multiplier une chane de caractres ne se fait pas du tout
comme la multiplication dun nombre. Pour certains types de donnes, la multiplication
na dailleurs aucun sens. Python associe donc chaque donne un type, qui va dfinir
les oprations autorises sur cette donne en particulier.

Les diffrents types de donnes


Nous nallons voir ici que les incontournables et les plus faciles manier. Des chapitres
entiers seront consacrs aux types plus complexes.
Les nombres entiers
Et oui, Python diffrencie les entiers des nombres virgule flottante !
Pourquoi cela ?

Initialement, cest surtout pour une question de place en mmoire mais, pour un ordinateur, les oprations que lon effectue sur des nombres virgule ne sont pas les mmes
que celles sur les entiers, et cette distinction reste encore dactualit de nos jours.
Le type entier se nomme int en Python (qui correspond langlais integer , cest-dire entier). La forme dun entier est un nombre sans virgule.
1

Nous avons vu au chapitre prcdent les oprations que lon pouvait effectuer sur ce type
de donnes et, mme si vous ne vous en souvenez pas, les deviner est assez lmentaire.
Les nombres flottants
Les flottants sont les nombres virgule. Ils se nomment float en Python (ce qui signifie
flottant en anglais). La syntaxe dun nombre flottant est celle dun nombre virgule
(noubliez pas de remplacer la virgule par un point). Si ce nombre na pas de partie
flottante mais que vous voulez quil soit considr par le systme comme un flottant,
vous pouvez lui ajouter une partie flottante de 0 (exemple 52.0).
1

3 . 152

Les nombres aprs la virgule ne sont pas infinis, puisque rien nest infini en informatique.
Mais la prcision est assez importante pour travailler sur des donnes trs fines.
Les chanes de caractres
Heureusement, les types de donnes disponibles en Python ne sont pas limits aux seuls
nombres, bien loin de l. Le dernier type simple que nous verrons dans ce chapitre
23

CHAPITRE 3. LE MONDE MERVEILLEUX DES VARIABLES


est la chane de caractres. Ce type de donne permet de stocker une srie de lettres,
pourquoi pas une phrase.
On peut crire une chane de caractres de diffrentes faons :
entre guillemets ("ceci est une chane de caractres") ;
entre apostrophes (ceci est une chane de caractres) ;
entre triples guillemets ("""ceci est une chane de caractres""").
On peut, linstar des nombres (et de tous les types de donnes) stocker une chane
de caractres dans une variable (ma_chaine = "Bonjour, la foule !")
Si vous utilisez les dlimiteurs simples (le guillemet ou lapostrophe) pour encadrer une
chane de caractres, il se pose le problme des guillemets ou apostrophes que peut
contenir ladite chane. Par exemple, si vous tapez chaine = Jaime le Python!,
vous obtenez le message suivant :
1
2
3
4

File " < stdin >" , line 1


chaine = J aime le Python !
^
SyntaxError : invalid syntax

Ceci est d au fait que lapostrophe de Jaime est considre par Python comme
la fin de la chane et quil ne sait pas quoi faire de tout ce qui se trouve au-del. Pour
pallier ce problme, il faut chapper les apostrophes se trouvant au cur de la chane.
On insre ainsi un caractre anti-slash \ avant les apostrophes contenues dans le
message.
1

chaine = J \ aime le Python !

On doit galement chapper les guillemets si on utilise les guillemets comme dlimiteurs.
1

chaine2 = "\" Le seul individu form , c est celui qui a appris


comment apprendre ( ... ) \" ( Karl Rogers , 1976) "

Le caractre dchappement \ est utilis pour crer dautres signes trs utiles. Ainsi,
\n symbolise un saut de ligne ("essai\nsur\nplusieurs\nlignes"). Pour crire
un vritable anti-slash dans une chane, il faut lchapper lui-mme (et donc crire
\\ ).
Linterprteur affiche les sauts de lignes comme on les saisit, cest--dire sous
forme de \n . Nous verrons dans la partie suivante comment afficher
rellement ces chanes de caractres et pourquoi linterprteur ne les affiche
pas comme il le devrait.
Utiliser les triples guillemets pour encadrer une chane de caractres dispense dchapper les guillemets et apostrophes, et permet dcrire plusieurs lignes sans symboliser
les retours la ligne au moyen de \n .

24

LES TYPES DE DONNES EN PYTHON

1
2
3
4

>>> chaine3 = """ Ceci est un nouvel


... essai sur plusieurs
... lignes """
>>>

Notez que les trois chevrons sont remplacs par trois points : cela signifie que linterprteur considre que vous navez pas fini dcrire cette instruction. En effet, celle-ci
ne sachve quune fois la chane referme avec trois nouveaux guillemets. Les sauts de
lignes seront automatiquement remplacs, dans la chane, par des \n .
Vous pouvez utiliser, la place des trois guillemets, trois apostrophes qui jouent exactement le mme rle. Je nutilise personnellement pas ces dlimiteurs, mais sachez quils
existent et ne soyez pas surpris si vous les voyez un jour dans un code source.
Voil, nous avons boucl le rapide tour dhorizon des types simples. Qualifier les chanes
de caractres de type simple nest pas strictement vrai mais nous nallons pas, dans ce
chapitre, entrer dans le dtail des oprations que lon peut effectuer sur ces chanes.
Cest inutile pour linstant et ce serait hors sujet. Cependant, rien ne vous empche
de tester vous mmes quelques oprations comme laddition et la multiplication (dans
le pire des cas, Python vous dira quil ne peut pas faire ce que vous lui demandez et,
comme nous lavons vu, il est peu rancunier).

Un petit bonus
Au chapitre prcdent, nous avons vu les oprateurs classiques pour manipuler des
nombres mais aussi, comme on le verra plus tard, dautres types de donnes. Dautres
oprateurs ont t crs afin de simplifier la manipulation des variables.
Vous serez amens par la suite, et assez rgulirement, incrmenter des variables. Lincrmentation dsigne laugmentation de la valeur dune variable dun certain nombre.
Jusquici, jai procd comme ci-dessous pour augmenter une variable de 1 :
1

variable = variable + 1

Cette syntaxe est claire et intuitive mais assez longue, et les programmeurs, tout le
monde le sait, sont des fainants ns. On a donc trouv plus court.
1

variable += 1

Loprateur += revient ajouter la variable la valeur qui suit loprateur. Les oprateurs -=, *= et /= existent galement, bien quils soient moins utiliss.

Quelques trucs et astuces pour vous faciliter la vie


Python propose un moyen simple de permuter deux variables (changer leur valeur).
Dans dautres langages, il est ncessaire de passer par une troisime variable qui retient
lune des deux valeurs. . . ici cest bien plus simple :
25

CHAPITRE 3. LE MONDE MERVEILLEUX DES VARIABLES

1
2
3
4
5
6
7
8

>>>
>>>
>>>
>>>
32
>>>
5
>>>

a = 5
b = 32
a , b = b , a # permutation
a
b

Comme vous le voyez, aprs lexcution de la ligne 3, les variables a et b ont chang
leurs valeurs. On retrouvera cette distribution daffectation bien plus loin.
On peut aussi affecter assez simplement une mme valeur plusieurs variables :
1
2
3
4
5
6

>>> x = y = 3
>>> x
3
>>> y
3
>>>

Enfin, ce nest pas encore dactualit pour vous mais sachez quon peut couper une
instruction Python, pour lcrire sur deux lignes ou plus.
1
2
3
4

>>> 1 + 4 - 3 * 19 + 33 - 45 * 2 + (8 - 3) \
... -6 + 23.5
-86.5
>>>

Comme vous le voyez, le symbole \ permet, avant un saut de ligne, dindiquer


Python que cette instruction se poursuit la ligne suivante . Vous pouvez ainsi
morceler votre instruction sur plusieurs lignes.

Premire utilisation des fonctions


Eh bien, tout cela avance gentiment. Je me permets donc dintroduire ici, dans ce
chapitre sur les variables, lutilisation des fonctions. Il sagit finalement bien davantage
dune application concrte de ce que vous avez appris linstant. Un chapitre entier sera
consacr aux fonctions, mais utiliser celles que je vais vous montrer nest pas sorcier et
pourra vous tre utile.

Utiliser une fonction


quoi servent les fonctions ?

26

PREMIRE UTILISATION DES FONCTIONS


Une fonction excute un certain nombre dinstructions dj enregistres. En gros, cest
comme si vous enregistriez un groupe dinstructions pour faire une action prcise et
que vous lui donniez un nom. Vous navez plus ensuite qu appeler cette fonction par
son nom autant de fois que ncessaire (cela vite bon nombre de rptitions). Mais
nous verrons tout cela plus en dtail par la suite.
La plupart des fonctions ont besoin dau moins un paramtre pour travailler sur une
donne ; ces paramtres sont des informations que vous passez la fonction afin quelle
travaille dessus. Les fonctions que je vais vous montrer ne font pas exception. Ce concept
vous semble peut-tre un peu difficile saisir dans son ensemble mais rassurez-vous,
les exemples devraient tout rendre limpide.
Les fonctions sutilisent en respectant la syntaxe suivante :
nom_de_la_fonction(parametre_1,parametre_2,...,parametre_n).
Vous commencez par crire le nom de la fonction.
Vous placez entre parenthses les paramtres de la fonction. Si la fonction nattend
aucun paramtre, vous devrez quand mme mettre les parenthses, sans rien entre
elles.

La fonction type
Dans la partie prcdente, je vous ai prsent les types de donnes simples, du moins
une partie dentre eux. Une des grandes puissances de Python est quil comprend
automatiquement de quel type est une variable et cela lors de son affectation. Mais il
est pratique de pouvoir savoir de quel type est une variable.
La syntaxe de cette fonction est simple :
1

type ( n om _de _l a_variable )

La fonction renvoie le type de la variable passe en paramtre. Vu que nous sommes


dans linterprteur de commandes, cette valeur sera affiche. Si vous saisissez dans
linterprteur les lignes suivantes :
1
2

>>> a = 3
>>> type ( a )

Vous obtenez :
1

< class int >

Python vous indique donc que la variable a appartient la classe des entiers. Cette
notion de classe ne sera pas approfondie avant bien des chapitres mais sachez quon
peut la rapprocher dun type de donne.
Vous pouvez faire le test sans passer par des variables :
1
2

>>> type (3.4)


< class float >

27

CHAPITRE 3. LE MONDE MERVEILLEUX DES VARIABLES


3
4
5

>>> type (" un essai ")


< class str >
>>>

str est labrviation de string qui signifie chane (sous-entendu, de caractres) en anglais.

La fonction print
La fonction print permet dafficher la valeur dune ou plusieurs variables.
Mais. . . on ne fait pas exactement la mme chose en saisissant juste le nom
de la variable dans linterprteur ?
Oui et non. Linterprteur affiche bien la valeur de la variable car il affiche automatiquement tout ce quil peut, pour pouvoir suivre les tapes dun programme. Cependant,
quand vous ne travaillerez plus avec linterprteur, taper simplement le nom de la variable naura aucun effet. De plus, et vous laurez sans doute remarqu, linterprteur
entoure les chanes de caractres de dlimiteurs et affiche les caractres dchappement,
tout ceci encore pour des raisons de clart.
La fonction print est ddie laffichage uniquement. Le nombre de ses paramtres est
variable, cest--dire que vous pouvez lui demander dafficher une ou plusieurs variables.
Considrez cet exemple :
1
2
3
4
5

>>>
>>>
>>>
>>>
>>>

a = 3
print ( a )
a = a + 3
b = a - 2
print (" a =" , a , " et b =" , b )

Le premier appel print se contente dafficher la valeur de la variable a, cest--dire


3 . Le second appel print affiche :
1

a = 6 et b = 4

Ce deuxime appel print est peut-tre un peu plus dur comprendre. En fait, on
passe quatre paramtres print, deux chanes de caractres et les variables a et b.
Quand Python interprte cet appel de fonction, il va afficher les paramtres dans lordre
de passage, en les sparant par un espace.
Relisez bien cet exemple, il montre tout lintrt des fonctions. Si vous avez du mal
le comprendre dans son ensemble, dcortiquez-le en prenant indpendamment chaque
paramtre.
28

PREMIRE UTILISATION DES FONCTIONS


Testez lutilisation de print avec dautres types de donnes et en insrant des chanes
avec des sauts de lignes et des caractres chapps, pour bien vous rendre compte de
la diffrence.
Un petit Hello World ! ?
Quand on fait un cours sur un langage, quel quil soit, il est dusage de prsenter le
programme Hello World ! , qui illustre assez rapidement la syntaxe superficielle dun
langage.
Le but du jeu est trs simple : crire un programme qui affiche Hello World !
lcran. Dans certains langages, notamment les langages compils, vous pourrez ncessiter jusqu une dizaine de lignes pour obtenir ce rsultat. En Python, comme nous
venons de le voir, il suffit dune seule ligne :
1

>>> print (" Hello World !")

Pour plus dinformations, nhsitez pas consulter la page Wikipdia consacre


Hello World ! ; vous avez mme des codes rdigs en diffrents langages de programmation, cela peut tre intressant.


Wikipdia - Hello World !
B
Code web : 696192

En rsum
Les variables permettent de conserver dans le temps des donnes de votre programme.
Vous pouvez vous servir de ces variables pour diffrentes choses : les afficher, faire
des calculs avec, etc.
Pour affecter une valeur une variable, on utilise la syntaxe nom_de_variable =
valeur.
Il existe diffrents types de variables, en fonction de linformation que vous dsirez
conserver : int, float, chane de caractres etc.
Pour afficher une donne, comme la valeur dune variable par exemple, on utilise la
fonction print.

29

CHAPITRE 3. LE MONDE MERVEILLEUX DES VARIABLES

30

Chapitre

Les structures conditionnelles


Difficult :
usqu prsent, nous avons test des instructions dune faon linaire : linterprteur
excutait au fur et mesure le code que vous saisissiez dans la console. Mais nos
programmes seraient bien pauvres si nous ne pouvions, de temps autre, demander
excuter certaines instructions dans un cas, et dautres instructions dans un autre cas.

Dans ce chapitre, je vais vous parler des structures conditionnelles, qui vont vous permettre
de faire des tests et daller plus loin dans la programmation.
Les conditions permettent dexcuter une ou plusieurs instructions dans un cas, dautres
instructions dans un autre cas.
Vous finirez ce chapitre en crant votre premier vrai programme : mme si vous ne
pensez pas encore pouvoir faire quelque chose de trs consistant, la fin de ce chapitre
vous aurez assez de matire pour coder un petit programme dans un but trs prcis.

31

CHAPITRE 4. LES STRUCTURES CONDITIONNELLES

Vos premires conditions et blocs dinstructions


Forme minimale en if
Les conditions sont un concept essentiel en programmation (oui oui, je me rpte force
mais il faut avouer que des concepts essentiels, on na pas fini den voir). Elles vont
vous permettre de faire une action prcise si, par exemple, une variable est positive,
une autre action si cette variable est ngative, ou une troisime action si la variable est
nulle. Comme un bon exemple vaut mieux que plusieurs lignes dexplications, voici un
exemple clair dune condition prise sous sa forme la plus simple.
Ds prsent dans mes exemples, jutiliserai des commentaires. Les commentaires sont des messages qui sont ignors par linterprteur et qui permettent
de donner des indications sur le code (car, vous vous en rendrez compte, relire
ses programmes aprs plusieurs semaines dabandon, sans commentaire, ce
peut tre parfois plus quardu). En Python, un commentaire dbute par un
dise ( # ) et se termine par un saut de ligne. Tout ce qui est compris entre
ce # et ce saut de ligne est ignor. Un commentaire peut donc occuper la
totalit dune ligne (on place le # en dbut de ligne) ou une partie seulement,
aprs une instruction (on place le # aprs la ligne de code pour la commenter
plus spcifiquement).
Cela tant pos, revenons nos conditions :
1
2
3
4
5
6
7

>>> # Premier exemple de condition


>>> a = 5
>>> if a > 0: # Si a est sup rieur 0
...
print (" a est sup rieur 0.")
...
a est sup rieur 0.
>>>

Dtaillons ce code, ligne par ligne :


1. La premire ligne est un commentaire dcrivant quil sagit du premier test de
condition. Elle est ignore par linterprteur et sert juste vous renseigner sur le
code qui va suivre.
2. Cette ligne, vous devriez la comprendre sans aucune aide. On se contente daffecter la valeur 5 la variable a.
3. Ici se trouve notre test conditionnel. Il se compose, dans lordre :
du mot cl if qui signifie si en anglais ;
de la condition proprement dite, a > 0, quil est facile de lire (une liste des
oprateurs autoriss pour la comparaison sera prsente plus bas) ;
du signe deux points, : , qui termine la condition et est indispensable :
Python affichera une erreur de syntaxe si vous lomettez.
32

VOS PREMIRES CONDITIONS ET BLOCS DINSTRUCTIONS


4. Ici se trouve linstruction  excuter dans le cas o a est suprieur 0. Aprs
que vous ayez appuy sur Entre  la fin de la ligne prcdente, linterprteur vous prsente la srie de trois points qui signifie quil attend la saisie du
bloc dinstructions concern avant de linterprter. Cette instruction (et les
autres instructions excuter sil y en a) est indente, cest--dire dcale vers la
droite. Des explications supplmentaires seront donnes un peu plus bas sur les
indentations.
5. Linterprteur vous affiche nouveau la srie de trois points et vous pouvez en
profiter pour saisir une nouvelle instruction dans ce bloc dinstructions. Ce nest
pas le cas pour linstant. Vous appuyez donc sur Entre  sans avoir rien crit
et linterprteur vous affiche le message a est suprieur 0 , ce qui est assez
logique vu que a est effectivement suprieur 0.
Il y a deux notions importantes sur lesquelles je dois prsent revenir, elles sont
complmentaires ne vous en faites pas.
La premire est celle de bloc dinstructions. On entend par bloc dinstructions une srie
dinstructions qui sexcutent dans un cas prcis (par condition, comme on vient de le
voir, par rptition, comme on le verra plus tard. . .). Ici, notre bloc nest constitu que
dune seule instruction (la ligne 4 qui fait appel print). Mais rien ne vous empche
de mettre plusieurs instructions dans ce bloc.
1
2
3
4
5
6
7

a = 5
b = 8
if a > 0:
# On incr mente la valeur de b
b += 1
# On affiche les valeurs des variables
print (" a =" ,a ," et b =" , b )

La seconde notion importante est celle dindentation. On entend par indentation un


certain dcalage vers la droite, obtenu par un (ou plusieurs) espaces ou tabulations.
Les indentations sont essentielles pour Python. Il ne sagit pas, comme dans dautres
langages tels que le C++ ou le Java, dun confort de lecture mais bien dun moyen
pour linterprteur de savoir o se trouvent le dbut et la fin dun bloc.

Forme complte (if, elif et else)


Les limites de la condition simple en if
La premire forme de condition que lon vient de voir est pratique mais assez incomplte.
Considrons, par exemple, une variable a de type entier. On souhaite faire une action
si cette variable est positive et une action diffrente si elle est ngative. Il est possible
dobtenir ce rsultat avec la forme simple dune condition :

33

CHAPITRE 4. LES STRUCTURES CONDITIONNELLES

1
2
3
4
5

>>> a = 5
>>> if a > 0: #
...
print (" a
... if a < 0: #
...
print (" a

Si a est positif
est positif .")
a est n gatif
est n gatif .")

Amusez-vous changer la valeur de a et excutez chaque fois les conditions ; vous


obtiendrez des messages diffrents, sauf si a est gal 0. En effet, aucune action na
t prvue si a vaut 0.
Cette mthode nest pas optimale, tout dabord parce quelle nous oblige crire deux
conditions spares pour tester une mme variable. De plus, et mme si cest dur
concevoir par cet exemple, dans le cas o la variable remplirait les deux conditions (ici
cest impossible bien entendu), les deux portions de code sexcuteraient.
La condition if est donc bien pratique mais insuffisante.

Linstruction else :
Le mot-cl else, qui signifie sinon en anglais, permet de dfinir une premire forme
de complment notre instruction if.
1
2
3
4
5

>>>
>>>
...
...
...

age = 21
if age >= 18: # Si age est sup rieur ou gal 18
print (" Vous tes majeur .")
else : # Sinon ( age inf rieur 18)
print (" Vous tes mineur .")

Je pense que cet exemple suffit amplement exposer lutilisation de else. La seule
subtilit est de bien se rendre compte que Python excute soit lun, soit lautre, et
jamais les deux. Notez que cette instruction else doit se trouver au mme niveau
dindentation que linstruction if quelle complte. De plus, elle se termine galement
par deux points puisquil sagit dune condition, mme si elle est sous-entendue.
Lexemple de tout lheure pourrait donc se prsenter comme suit, avec lutilisation
de else :
1
2
3
4
5

>>> a = 5
>>> if a > 0:
...
print (" a est sup rieur 0.")
... else :
...
print (" a est inf rieur ou gal 0.")

Mais. . . le rsultat nest pas tout fait le mme, si ?

34

VOS PREMIRES CONDITIONS ET BLOCS DINSTRUCTIONS


Non, en effet. Vous vous rendrez compte que, cette fois, le cas o a vaut 0 est bien pris en
compte. En effet, la condition initiale prvoit dexcuter le premier bloc dinstructions
si a est strictement suprieur 0. Sinon, on excute le second bloc dinstructions.
Si lon veut faire la diffrence entre les nombres positifs, ngatifs et nuls, il va falloir
utiliser une condition intermdiaire.

Linstruction elif :
Le mot cl elif est une contraction de else if , que lon peut traduire trs littralement par sinon si . Dans lexemple que nous venons juste de voir, lidal serait
dcrire :
si a est strictement suprieur 0, on dit quil est positif ;
sinon si a est strictement infrieur 0, on dit quil est ngatif ;
sinon, (a ne peut qutre gal 0), on dit alors que a est nul.
Traduit en langage Python, cela donne :
1
2
3
4
5
6

>>> if a > 0: # Positif


...
print (" a est positif .")
... elif a < 0: # N gatif
...
print (" a est n gatif .")
... else : # Nul
print (" a est nul .")

De mme que le else, le elif est sur le mme niveau dindentation que le if initial. Il
se termine aussi par deux points. Cependant, entre le elif et les deux points se trouve
une nouvelle condition. Linairement, le schma dexcution se traduit comme suit :
1. On regarde si a est strictement suprieur 0. Si cest le cas, on affiche a est
positif et on sarrte l.
2. Sinon, on regarde si a est strictement infrieur 0. Si cest le cas, on affiche a
est ngatif et on sarrte.
3. Sinon, on affiche a est nul .
Attention : quand je dis on sarrte , il va de soi que cest uniquement
pour cette condition. Sil y a du code aprs les trois blocs dinstructions, il
sera excut dans tous les cas.
Vous pouvez mettre autant de elif que vous voulez aprs une condition en if. Tout
comme le else, cette instruction est facultative et, quand bien mme vous construiriez
une instruction en if, elif, vous ntes pas du tout oblig de prvoir un else aprs.
En revanche, linstruction else ne peut figurer quune fois, clturant le bloc de la
condition. Deux instructions else dans une mme condition ne sont pas envisageables
et nauraient de toute faon aucun sens.
35

CHAPITRE 4. LES STRUCTURES CONDITIONNELLES


Sachez quil est heureusement possible dimbriquer des conditions et, dans ce cas, lindentation permet de comprendre clairement le schma dexcution du programme. Je
vous laisse essayer cette possibilit, je ne vais pas tout faire votre place non plus. :-)

De nouveaux oprateurs
Les oprateurs de comparaison
Les conditions doivent ncessairement introduire de nouveaux oprateurs, dits oprateurs de comparaison. Je vais les prsenter trs brivement, vous laissant linitiative
de faire des tests car ils ne sont rellement pas difficiles comprendre.
Oprateur
<
>
<=
>=
==
!=

Signification littrale
Strictement infrieur
Strictement suprieur
Infrieur ou gal
Suprieur ou gal
gal
Diffrent de

Attention : lgalit de deux valeurs est compare avec loprateur ==


et non = . Ce dernier est en effet loprateur daffectation et ne doit pas
tre utilis dans une condition.

Prdicats et boolens
Avant daller plus loin, sachez que les conditions qui se trouvent, par exemple, entre
if et les deux points sont appels des prdicats. Vous pouvez tester ces prdicats
directement dans linterprteur pour comprendre les explications qui vont suivre.
1
2
3
4
5
6
7
8

>>> a
>>> a
False
>>> a
True
>>> a
True
>>>

= 0
== 5
> -8
!= 33.19

Linterprteur renvoie tantt True (cest--dire vrai ), tantt False (cest--dire


faux ).
True et False sont les deux valeurs possibles dun type que nous navons pas vu
jusquici : le type boolen (bool).
36

DE NOUVEAUX OPRATEURS
Noubliez pas que True et False sont des valeurs ayant leur premire lettre en
majuscule. Si vous commencez crire True sans un T majuscule, Python
ne va pas comprendre.
Les variables de ce type ne peuvent prendre comme valeur que vrai ou faux et peuvent
tre pratiques, justement, pour stocker des prdicats, de la faon que nous avons vue
ou dune faon plus dtourne.
1
2
3
4
5

>>> age = 21
>>> majeur = False
>>> if age >= 18:
>>>
majeur = True
>>>

la fin de cet exemple, majeur vaut True, cest--dire vrai , si lge est suprieur ou
gal 18. Sinon, il continue de valoir False. Les boolens ne vous semblent peut-tre
pas trs utiles pour linstant mais vous verrez quils rendent de grands services !

Les mots-cls and, or et not


Il arrive souvent que nos conditions doivent tester plusieurs prdicats, par exemple
quand lon cherche vrifier si une variable quelconque, de type entier, se trouve dans
un intervalle prcis (cest--dire comprise entre deux nombres). Avec nos mthodes
actuelles, le plus simple serait dcrire :
1
2
3
4
5
6
7
8
9

# On fait un test pour savoir si a est comprise dans l


intervalle allant de 2 8 inclus
a = 5
if a >= 2:
if a <= 8:
print (" a est dans l intervalle .")
else :
print (" a n est pas dans l intervalle .")
else :
print (" a n est pas dans l intervalle .")

Cela marche mais cest assez lourd, dautant que, pour tre sr quun message soit
affich chaque fois, il faut fermer chacune des deux conditions laide dun else
(la seconde tant imbrique dans la premire). Si vous avez du mal comprendre cet
exemple, prenez le temps de le dcortiquer, ligne par ligne, il ny a rien que de trs
simple.
Il existe cependant le mot cl and (qui signifie et en anglais) qui va nous rendre ici
un fier service. En effet, on cherche tester la fois si a est suprieur ou gal 2 et
infrieur ou gal 8. On peut donc rduire ainsi les conditions imbriques :
1
2

if a >=2 and a <=8:


print (" a est dans l intervalle .")

37

CHAPITRE 4. LES STRUCTURES CONDITIONNELLES


3
4

else :
print (" a n est pas dans l intervalle .")

Simple et bien plus comprhensible, avouez-le.


Sur le mme mode, il existe le mot cl or qui signifie cette fois ou . Nous allons
prendre le mme exemple, sauf que nous allons valuer notre condition diffremment.
Nous allons chercher savoir si a nest pas dans lintervalle. La variable ne se trouve
pas dans lintervalle si elle est infrieure 2 ou suprieure 8. Voici donc le code :
1
2
3
4

if a <2 or a >8:
print (" a n est pas dans l intervalle .")
else :
print (" a est dans l intervalle .")

Enfin, il existe le mot cl not qui inverse un prdicat. Le prdicat not a==5 quivaut
donc a!=5.
not rend la syntaxe plus claire. Pour cet exemple, jajoute la liste un nouveau mot cl,
is, qui teste lgalit non pas des valeurs de deux variables, mais de leurs rfrences.
Je ne vais pas rentrer dans le dtail de ce mcanisme avant longtemps. Il vous suffit de
savoir que pour les entiers, les flottants et les boolens, cest strictement la mme chose.
Mais pour tester une galit entre variables dont le type est plus complexe, prfrez
loprateur == . Revenons cette dmonstration :
1
2
3
4
5
6

>>> majeur = False


>>> if majeur is not True :
...
print (" Vous n tes pas encore majeur .")
...
Vous n tes pas encore majeur .
>>>

Si vous parlez un minimum langlais, ce prdicat est limpide et dune simplicit sans
gale.
Vous pouvez tester des prdicats plus complexes de la mme faon que les prcdents,
en les saisissant directement, sans le if ni les deux points, dans linterprteur de commande. Vous pouvez utiliser les parenthses ouvrantes et fermantes pour encadrer des
prdicats et les comparer suivant des priorits bien prcises (nous verrons ce point plus
loin, si vous nen comprenez pas lutilit).

Votre premier programme !

quoi on joue ?

38

VOTRE PREMIER PROGRAMME !


Lheure du premier TP est venue. Comme il sagit du tout premier, et parce quil y a
quelques indications que je dois vous donner pour que vous parveniez jusquau bout,
je vous accompagnerai pas pas dans sa ralisation.

Avant de commencer
Vous allez dans cette section crire votre premier programme. Vous allez srement
tester les syntaxes directement dans linterprteur de commandes.
Vous pourriez prfrer crire votre code directement dans un fichier que vous
pouvez ensuite excuter. Si cest le cas, je vous renvoie au chapitre traitant
de ce point, que vous trouverez la page 387 de ce livre.

Sujet
Le but de notre programme est de dterminer si une anne saisie par lutilisateur est
bissextile. Il sagit dun sujet trs pris des enseignants en informatique quand il sagit
dexpliquer les conditions. Mille pardons, donc, ceux qui ont dj fait cet exercice
dans un autre langage mais je trouve que ce petit programme reprend assez de thmes
abords dans ce chapitre pour tre rellement intressant.
Je vous rappelle les rgles qui dterminent si une anne est bissextile ou non (vous allez
peut-tre mme apprendre des choses que le commun des mortels ignore).
Une anne est dite bissextile si cest un multiple de 4, sauf si cest un multiple de 100.
Toutefois, elle est considre comme bissextile si cest un multiple de 400. Je dveloppe :
Si une anne nest pas multiple de 4, on sarrte l, elle nest pas bissextile.
Si elle est multiple de 4, on regarde si elle est multiple de 100.
Si cest le cas, on regarde si elle est multiple de 400.
Si cest le cas, lanne est bissextile.
Sinon, elle nest pas bissextile.
Sinon, elle est bissextile.

Solution ou rsolution
Voil. Le problme est pos clairement (sinon relisez attentivement lnonc autant de
fois que ncessaire), il faut maintenant rflchir sa rsolution en termes de programmation. Cest une phase de transition assez dlicate de prime abord et je vous conseille
de schmatiser le problme, de prendre des notes sur les diffrentes tapes, sans pour
linstant penser au code. Cest une phase purement algorithmique, autrement dit, on
rflchit au programme sans rflchir au code proprement dit.
Vous aurez besoin, pour raliser ce petit programme, de quelques indications qui sont
rellement spcifiques Python. Ne lisez donc ceci quaprs avoir cern et clairement
crit le problme dune faon plus algorithmique. Cela tant dit, si vous peinez trouver
39

CHAPITRE 4. LES STRUCTURES CONDITIONNELLES


une solution, ne vous y attardez pas. Cette phase de rflexion est assez difficile au dbut
et, parfois il suffit dun peu de pratique et dexplications pour comprendre lessentiel.

La fonction input()
Tout dabord, jai mentionn une anne saisie par lutilisateur. En effet, depuis tout
lheure, nous testons des variables que nous dclarons nous-mmes, avec une valeur
prcise. La condition est donc assez ridicule.
input() est une fonction qui va, pour nous, caractriser nos premires interactions
avec lutilisateur : le programme ragira diffremment en fonction du nombre saisi par
lutilisateur.
input() accepte un paramtre facultatif : le message afficher lutilisateur. Cette
instruction interrompt
le programme et attend que lutilisateur saisisse ce quil veut

puis appuie sur Entre . cet instant, la fonction renvoie ce que lutilisateur a saisi.
Il faut donc piger cette valeur dans une variable.
1
2
3
4
5
6

>>> # Test de la fonction input


>>> annee = input (" Saisissez une ann e : ")
Saisissez une ann e : 2009
>>> print ( annee )
2009
>>>

Il subsiste un problme : le type de la variable annee aprs lappel input() est. . . une
chane de caractres. Vous pouvez vous en rendre compte grce aux apostrophes qui
encadrent la valeur de la variable quand vous laffichez directement dans linterprteur.
Cest bien ennuyeux : nous qui voulions travailler sur un entier, nous allons devoir
convertir cette variable. Pour convertir une variable vers un autre type, il faut utiliser
le nom du type comme une fonction (cest dailleurs exactement ce que cest).
1
2
3
4
5
6
7
8
9
10
11

>>> type ( annee )


< type str >
>>> # On veut convertir la variable en un entier , on utilise
>>> # donc la fonction int qui prend en param tre la variable
>>> # d origine
>>> annee = int ( annee )
>>> type ( annee )
< type int >
>>> print ( annee )
2009
>>>

Bon, parfait ! On a donc maintenant lanne sous sa forme entire. Notez que, si vous
saisissez des lettres lors de lappel input(), la conversion renverra une erreur.
40

VOTRE PREMIER PROGRAMME !


Lappel la fonction int() en a peut-tre dconcert certains. On passe
en paramtre de cette fonction la variable contenant la chane de caractres
issue de input(), pour tenter de la convertir. La fonction int() renvoie la
valeur convertie en entier et on la rcupre donc dans la mme variable. On
vite ainsi de travailler sur plusieurs variables, sachant que la premire na
plus aucune utilit prsent quon la convertie.

Test de multiples
Certains pourraient galement se demander comment tester si un nombre a est multiple
dun nombre b. Il suffit, en fait, de tester le reste de la division entire de b par a. Si
ce reste est nul, alors a est un multiple de b.
1
2
3
4
5

>>> 5 % 2 # 5 n est pas un multiple de 2


1
>>> 8 % 2 # 8 est un multiple de 2
0
>>>

vous de jouer
Je pense vous avoir donn tous les lments ncessaires pour russir. mon avis, le plus
difficile est la phase de rflexion qui prcde la composition du programme. Si vous avez
du mal raliser cette opration, passez la correction et tudiez-la soigneusement.
Sinon, on se retrouve la section suivante.
Bonne chance !

Correction
Cest lheure de comparer nos mthodes et, avant de vous divulguer le code de ma
solution, je vous prcise quelle est loin dtre la seule possible. Vous pouvez trs bien
avoir trouv quelque chose de diffrent mais qui fonctionne tout aussi bien.
Attention. . . la voiiiciiiiiii. . .
1
2

# Programme testant si une ann e , saisie par l ' utilisateur ,


# est bissextile ou non

3
4
5
6
7

annee = input ( " Saisissez une ann e : " ) # On attend que l '
utilisateur saisisse l ' ann e qu ' il d sire tester
annee = int ( annee ) # Risque d ' erreur si l ' utilisateur n 'a pas
saisi un nombre
bissextile = False # On cr e un bool en qui vaut vrai ou faux
# selon que l ' ann e est bissextile ou non

41

CHAPITRE 4. LES STRUCTURES CONDITIONNELLES


9
10
11
12
13
14
15
16

if annee % 400 == 0 :
bissextile = True
elif annee % 100 == 0 :
bissextile = False
elif annee % 4 == 0 :
bissextile = True
else :
bissextile = False

17
18
19
20
21

if bissextile : # Si l ' ann e est bissextile


print ( " L ' ann e saisie est bissextile . " )
else :
print ( " L ' ann e saisie n ' est pas bissextile . " )

Je vous rappelle que vous pouvez enregistrer vos codes dans des fichiers afin de les
excuter. Je vous renvoie la page 387 pour plus dinformations.
Je pense que le code est assez clair, reste expliciter lenchanement des conditions.
Vous remarquerez quon a invers le problme. On teste en effet dabord si lanne est
un multiple de 400, ensuite si cest un multiple de 100, et enfin si cest un multiple de 4.
En effet, le elif garantit que, si annee est un multiple de 100, ce nest pas un multiple
de 400 (car le cas a t trait au-dessus). De cette faon, on sassure que tous les cas
sont grs. Vous pouvez faire des essais avec plusieurs annes et vous rendre compte si
le programme a raison ou pas.
Lutilisation de bissextile comme dun prdicat part entire vous a
peut-tre dconcerts. Cest en fait tout fait possible et logique, puisque
bissextile est un boolen. Il est de ce fait vrai ou faux et donc on peut le tester simplement. On peut bien entendu aussi crire if bissextile==True:,
cela revient au mme.

Un peu doptimisation
Ce quon a fait tait bien mais on peut lamliorer. Dailleurs, vous vous rendrez compte
que cest presque toujours le cas. Ici, il sagit bien entendu de notre condition, que je
vais passer au crible afin den construire une plus courte et plus logique, si possible. On
peut parler doptimisation dans ce cas, mme si loptimisation intgre aussi et surtout
les ressources consommes par votre application, en vue de diminuer ces ressources et
damliorer la rapidit de lapplication. Mais, pour une petite application comme celleci, je ne pense pas quon perdra du temps sur loptimisation du temps dexcution.
Le premier dtail que vous auriez pu remarquer, cest que le else de fin est inutile. En
effet, la variable bissextile vaut par dfaut False et conserve donc cette valeur si le
cas nest pas trait (ici, quand lanne nest ni un multiple de 400, ni un multiple de
100, ni un multiple de 4).
Ensuite, il apparat que nous pouvons faire un grand mnage dans notre condition car
les deux seuls cas correspondant une anne bissextile sont si lanne est un multiple
42

VOTRE PREMIER PROGRAMME !


de 400 ou si lanne est un multiple de 4 mais pas de 100 .
Le prdicat correspondant est un peu dlicat, il fait appel aux priorits des parenthses.
Je ne mattendais pas que vous le trouviez tout seuls mais je souhaite que vous le
compreniez bien prsent.
1

# Programme testant si une ann e , saisie par l ' utilisateur , est


bissextile ou non

2
3
4

annee = input ( " Saisissez une ann e : " ) # On attend que l '
utilisateur saisisse l ' ann e qu ' il d sire tester
annee = int ( annee ) # Risque d ' erreur si l ' utilisateur n 'a pas
saisi un nombre

5
6
7
8
9

if annee % 400 == 0 or ( annee % 4 == 0 and annee % 100 != 0 ) :


print ( " L ' ann e saisie est bissextile . " )
else :
print ( " L ' ann e saisie n ' est pas bissextile . " )


Copier ce code
B
Code web : 886842


Du coup, on na plus besoin de la variable bissextile, cest dj cela de gagn. Nous
sommes passs de 16 lignes de code seulement 7 (sans compter les commentaires et
les sauts de ligne) ce qui nest pas rien.

En rsum
Les conditions permettent dexcuter certaines instructions dans certains cas, dautres
instructions dans un autre cas.
Les conditions sont marques par les mot-cls if ( si ), elif ( sinon si ) et else
( sinon ).
Les mot-cls if et elif doivent tre suivis dun test (appel aussi prdicat).
Les boolens sont des donnes soit vraies (True) soit fausses (False).

43

CHAPITRE 4. LES STRUCTURES CONDITIONNELLES

44

Chapitre

Les boucles
Difficult :
es boucles sont un concept nouveau pour vous. Elles vont vous permettre de rpter
une certaine opration autant de fois que ncessaire. Le concept risque de vous sembler
un peu thorique car les applications pratiques prsentes dans ce chapitre ne vous
paratront probablement pas trs intressantes. Toutefois, il est impratif que cette notion
soit comprise avant que vous ne passiez la suite. Viendra vite le moment o vous aurez
du mal crire une application sans boucle.

En outre, les boucles peuvent permettre de parcourir certaines squences comme les chanes
de caractres pour, par exemple, en extraire chaque caractre.
Alors, on commence ?

45

CHAPITRE 5. LES BOUCLES

En quoi cela consiste-t-il ?


Comme je lai dit juste au-dessus, les boucles constituent un moyen de rpter un certain
nombre de fois des instructions de votre programme. Prenons un exemple simple, mme
sil est assez peu rjouissant en lui-mme : crire un programme affichant la table de
multiplication par 7, de 1 * 7 10 * 7.
. . . bah quoi ?
Bon, ce nest quun exemple, ne faites pas cette tte, et puis je suis sr que ce sera utile
pour certains. Dans un premier temps, vous devriez arriver au programme suivant :
1
2
3
4
5
6
7
8
9
10

print ( " 1
print ( " 2
print ( " 3
print ( " 4
print ( " 5
print ( " 6
print ( " 7
print ( " 8
print ( " 9
print ( " 10

*
*
*
*
*
*
*
*
*
*

7
7
7
7
7
7
7
7
7
7

=",
=",
=",
=",
=",
=",
=",
=",
=",
=",

1 * 7)
2 * 7)
3 * 7)
4 * 7)
5 * 7)
6 * 7)
7 * 7)
8 * 7)
9 * 7)
10 * 7 )

. . . et le rsultat :
1
2
3
4
5
6
7
8
9
10

1
2
3
4
5
6
7
8
9
10

*
*
*
*
*
*
*
*
*
*

7
7
7
7
7
7
7
7
7
7

=
=
=
=
=
=
=
=
=
=

7
14
21
28
35
42
49
56
63
70

Je vous rappelle que vous pouvez enregistrer vos codes dans des fichiers. Vous
trouverez la marche suivre la page 387 de ce livre.
Bon, cest srement la premire ide qui vous est venue et cela fonctionne, trs bien
mme. Seulement, vous reconnatrez quun programme comme cela nest pas bien utile.
Essayons donc le mme programme mais, cette fois-ci, en utilisant une variable ; ainsi,
si on dcide dafficher la table de multiplication de 6, on naura qu changer la valeur
de la variable ! Pour cet exemple, on utilise une variable nb qui contiendra 7. Les
instructions seront lgrement diffrentes mais vous devriez toujours pouvoir crire ce
programme :
1
2

46

nb = 7
print ( " 1 * " , nb , " = " , 1 * nb )

LA BOUCLE WHILE
3
4
5
6
7
8
9
10
11

print ( " 2
print ( " 3
print ( " 4
print ( " 5
print ( " 6
print ( " 7
print ( " 8
print ( " 9
print ( " 10

*",
*",
*",
*",
*",
*",
*",
*",
*",

nb ,
nb ,
nb ,
nb ,
nb ,
nb ,
nb ,
nb ,
nb ,

"=",
"=",
"=",
"=",
"=",
"=",
"=",
"=",
"=",

2 * nb )
3 * nb )
4 * nb )
5 * nb )
6 * nb )
7 * nb )
8 * nb )
9 * nb )
10 * nb )

Le rsultat est le mme, vous pouvez vrifier. Mais le code est quand-mme un peu
plus intressant : on peut changer la table de multiplication afficher en changeant la
valeur de la variable nb.
Mais ce programme reste assez peu pratique et il accomplit une tche bien rptitive.
Les programmeurs tant trs paresseux, ils prfrent utiliser les boucles.

La boucle while
La boucle que je vais prsenter se retrouve dans la plupart des autres langages de
programmation et porte le mme nom. Elle permet de rpter un bloc dinstructions
tant quune condition est vraie (while signifie tant que en anglais). Jespre que le
concept de bloc dinstructions est clair pour vous, sinon je vous renvoie au chapitre
prcdent.
La syntaxe de while est :
1
2
3
4
5

while
#
#
#
#

condition :
instruction 1
instruction 2
...
instruction N

Vous devriez reconnatre la forme dun bloc dinstructions, du moins je lespre.

Quelle condition va-t-on utiliser ?

Eh bien, cest l le point important. Dans cet exemple, on va crer une variable qui
sera incrmente dans le bloc dinstructions. Tant que cette variable sera infrieure
10, le bloc sexcutera pour afficher la table.
Si ce nest pas clair, regardez ce code, quelques commentaires suffiront pour le comprendre :
1
2

nb = 7 # On garde la variable contenant le nombre dont on veut


la table de multiplication
i = 0 # C ' est notre variable compteur que nous allons incr
menter dans la boucle

47

CHAPITRE 5. LES BOUCLES


3
4
5
6

while i < 10 : # Tant que i est strictement inf rieure 10


print ( i + 1 , " * " , nb , " = " , ( i + 1 ) * nb )
i += 1 # On incr mente i de 1 chaque tour de boucle

Analysons ce code ligne par ligne :


1. On instancie la variable nb qui accueille le nombre sur lequel nous allons travailler (en loccurence, 7). Vous pouvez bien entendu faire saisir ce nombre par
lutilisateur, vous savez le faire prsent.
2. On instancie la variable i qui sera notre compteur durant la boucle. i est un
standard utilis quand il est question de boucles et de variables sincrmentant
mais il va de soi que vous auriez pu lui donner un autre nom. On linitialise 0.
3. Un saut de ligne ne fait jamais de mal !
4. On trouve ici linstruction while qui se dcode, comme je lai indiqu en commentaire, en tant que i est strictement infrieure 10 . Noubliez pas
les deux points la fin de la ligne.
5. La ligne du print, vous devez la reconnatre. Maintenant, la plus grande partie
de la ligne affiche est constitue de variables, part les signes mathmatiques.
Vous remarquez qu chaque fois quon utilise i dans cette ligne, pour laffichage
ou le calcul, on lui ajoute 1 : cela est d au fait quen programmation, on a
lhabitude (habitude que vous devrez prendre) de commencer compter partir
de 0. Seulement ce nest pas le cas de la table de multiplication, qui va de 1
10 et non de 0 9, comme cest le cas pour les valeurs de i. Certes, jaurais pu
changer la condition et la valeur initiale de i, ou mme placer lincrmentation
de i avant laffichage, mais jai voulu prendre le cas le plus courant, le format de
boucle que vous retrouverez le plus souvent. Rien ne vous empche de faire les
tests et je vous y encourage mme.
6. Ici, on incrmente la variable i de 1. Si on est dans le premier tour de boucle,
i passe donc de 0 1. Et alors, puisquil sagit de la fin du bloc dinstructions,
on revient linstruction while. while vrifie que la valeur de i est toujours
infrieure 10. Si cest le cas (et a lest pour linstant), on excute nouveau le
bloc dinstructions. En tout, on excute ce bloc 10 fois, jusqu ce que i passe de
9 10. Alors, linstruction while vrifie la condition, se rend compte quelle est
prsent fausse (la valeur de i nest pas infrieure 10 puisquelle est maintenant
gale 10) et sarrte. Sil y avait du code aprs le bloc, il serait prsent excut.
Noubliez pas dincrmenter i ! Sinon, vous crez ce quon appelle une boucle
infinie, puisque la valeur de i nest jamais suprieure 10 et la condition du
while, par consquent, toujours vraie. . . La boucle sexcute donc linfini,
du moins en thorie. Si votre ordinateur se lance dans une boucle infinie
programme, pour interrompre la boucle, vous devrez taper
cause de votre

CTRL
+
C
dans
la fentre de linterprteur (sous Windows ou Linux).

  
Python ne le fera pas tout seul car, pour lui, il se passe bel et bien quelque
chose. De toute faon, il est incapable de diffrencier une boucle infinie dune
boucle finie : cest au programmeur de le faire.
48

LA BOUCLE FOR

La boucle for
Comme je lai dit prcdemment, on retrouve linstruction while dans la plupart des
autres langages. Dans le C++ ou le Java, on retrouve galement des instructions for
mais qui nont pas le mme sens. Cest assez particulier et cest le point sur lequel je
risque de manquer dexemples dans limmdiat, toute son utilit se rvlant au chapitre
sur les listes. Notez que, si vous avez fait du Perl ou du PHP, vous pouvez retrouver
les boucles for sous un mot-cl assez proche : foreach.
Linstruction for travaille sur des squences. Elle est en fait spcialise dans le parcours
dune squence de plusieurs donnes. Nous navons pas vu (et nous ne verrons pas tout
de suite) ces squences assez particulires mais trs rpandues, mme si elles peuvent
se rvler complexes. Toutefois, il en existe un type que nous avons rencontr depuis
quelque temps dj : les chanes de caractres.
Les chanes de caractres sont des squences. . . de caractres ! Vous pouvez parcourir
une chane de caractres (ce qui est galement possible avec while mais nous verrons
plus tard comment). Pour linstant, intressons-nous for.
Linstruction for se construit ainsi :
1

for element in sequence :

element est une variable cre par le for, ce nest pas vous de linstancier. Elle prend
successivement chacune des valeurs figurant dans la squence parcourue.
Ce nest pas trs clair ? Alors, comme dhabitude, tout sclaire avec le code !
1
2
3

chaine = " Bonjour les ZER0S "


for lettre in chaine :
print ( lettre )

Ce qui nous donne le rsultat suivant :


1
2
3
4
5
6
7

B
o
n
j
o
u
r

8
9
10
11

l
e
s

12
13
14
15
16
17

Z
E
R
0
S

49

CHAPITRE 5. LES BOUCLES


Est-ce plus clair ? En fait, la variable lettre prend successivement la valeur de chaque
lettre contenue dans la chane de caractres (dabord B, puis o, puis n. . .). On affiche
ces valeurs avec print et cette fonction revient la ligne aprs chaque message, ce
qui fait que toutes les lettres sont sur une seule colonne. Littralement, la ligne 2
signifie pour lettre dans chaine . Arriv cette ligne, linterprteur va crer
une variable lettre qui contiendra le premier lment de la chane (autrement dit,
la premire lettre). Aprs lexcution du bloc, la variable lettre contient la seconde
lettre, et ainsi de suite tant quil y a une lettre dans la chane.
Notez bien que, du coup, il est inutile dincrmenter la variable lettre (ce qui serait
dailleurs assez ridicule vu que ce nest pas un nombre). Python se charge de lincrmentation, cest lun des grands avantages de linstruction for.
linstar des conditions que nous avons vues jusquici, in peut tre utilise ailleurs
que dans une boucle for.
1
2
3
4
5
6

chaine = " Bonjour les ZER0S "


for lettre in chaine :
if lettre in " AEIOUYaeiouy " : # lettre est une voyelle
print ( lettre )
else : # lettre est une consonne ... ou plus exactement ,
lettre n ' est pas une voyelle
print ( " * " )

. . . ce qui donne :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

*
o
*
*
o
u
*
*
*
e
*
*
*
E
*
*
*

Voil ! Linterprteur affiche les lettres si ce sont des voyelles et, sinon, il affiche des
* . Notez bien que le 0 nest pas affich la fin, Python ne se doute nullement quil
sagit dun o stylis.
Retenez bien cette utilisation de in dans une condition. On cherche savoir si un
lment quelconque est contenu dans un ensemble donn (ici, si la lettre est contenue
dans AEIOUYaeiouy , cest--dire si lettre est une voyelle). On retrouvera plus
50

UN PETIT BONUS : LES MOTS-CLS BREAK ET CONTINUE


loin cette fonctionnalit.

Un petit bonus : les mots-cls break et continue


Je vais ici vous montrer deux nouveaux mots-cls, break et continue. Vous ne les
utiliserez peut-tre pas beaucoup mais vous devez au moins savoir quils existent. . . et
quoi ils servent.

Le mot-cl break
Le mot-cl break permet tout simplement dinterrompre une boucle. Il est souvent
utilis dans une forme de boucle que je napprouve pas trop :
1
2
3
4
5

while 1 : # 1 est toujours vrai -> boucle infinie


lettre = input ( " Tapez 'Q ' pour quitter : " )
if lettre == " Q " :
print ( " Fin de la boucle " )
break

La boucle while a pour condition 1, cest--dire une condition qui sera toujours vraie.
Autrement dit, en regardant la ligne du while, on pense une boucle infinie. En
pratique, on demande lutilisateur de taper une lettre (un Q pour quitter). Tant que
lutilisateur ne saisit pas cette lettre, le programme lui redemande de taper une lettre.
Quand il tape Q, le programme affiche Fin de la boucle et la boucle sarrte grce
au mot-cl break.
Ce mot-cl permet darrter une boucle quelle que soit la condition de la boucle. Python
sort immdiatement de la boucle et excute le code qui suit la boucle, sil y en a.
Cest un exemple un peu simpliste mais vous pouvez voir lide densemble. Dans ce
cas-l et, mon sens, dans la plupart des cas o break est utilis, on pourrait sen
sortir en prcisant une vritable condition la ligne du while. Par exemple, pourquoi
ne pas crer un boolen qui sera vrai tout au long de la boucle et faux quand la boucle
doit sarrter ? Ou bien tester directement si lettre != Q dans le while ?
Parfois, break est vritablement utile et fait gagner du temps. Mais ne lutilisez pas
outrance, prfrez une boucle avec une condition claire plutt quun bloc dinstructions
avec un break, qui sera plus dur apprhender dun seul coup dil.

Le mot-cl continue
Le mot-cl continue permet de. . . continuer une boucle, en repartant directement la
ligne du while ou for. Un petit exemple simpose, je pense :
1
2
3
4

i = 1
while i < 20 : # Tant que i est inf rieure 20
if i % 3 == 0 :
i += 4 # On ajoute 4 i

51

CHAPITRE 5. LES BOUCLES


print ( " On incr mente i de 4 . i est maintenant gale " ,
i)
continue # On retourne au while sans ex cuter les
autres lignes
print ( " La variable i = " , i )
i += 1 # Dans le cas classique on ajoute juste 1 i

5
6
7
8

Voici le rsultat :
1
2
3
4
5
6
7
8
9
10

La
La
On
La
La
On
La
La
On
La

variable i
variable i
incr mente
variable i
variable i
incr mente
variable i
variable i
incr mente
variable i

=
=
i
=
=
i
=
=
i
=

1
2
de 4. i est maintenant gale 7
7
8
de 4. i est maintenant gale 13
13
14
de 4. i est maintenant gale 19
19

Comme vous le voyez, tous les trois tours de boucle, i sincrmente de 4. Arriv au motcl continue, Python nexcute pas la fin du bloc mais revient au dbut de la boucle
en testant nouveau la condition du while. Autrement dit, quand Python arrive la
ligne 6, il saute la ligne 2 sans excuter les lignes 7 et 8. Au nouveau tour de boucle,
Python reprend lexcution normale de la boucle (continue nignore la fin du bloc que
pour le tour de boucle courant).
Mon exemple ne dmontre pas de manire clatante lutilit de continue. Les rares fois
o jutilise ce mot-cl, cest par exemple pour supprimer des lments dune liste, mais
nous navons pas encore vu les listes. Lessentiel, pour linstant, cest que vous vous
souveniez de ces deux mots-cls et que vous sachiez ce quils font, si vous les rencontrez
au dtour dune instruction. Personnellement, je nutilise pas trs souvent ces mots-cls
mais cest aussi une question de got.

En rsum
Une boucle sert rpter une portion de code en fonction dun prdicat.
On peut crer une boucle grce au mot-cl while suivi dun prdicat.
On peut parcourir une squence grce la syntaxe for element in sequence:.

52

Chapitre

Pas pas vers la modularit (1/2)


Difficult :
n programmation, on est souvent amen utiliser plusieurs fois des groupes dinstructions dans un but trs prcis. Attention, je ne parle pas ici de boucles. Simplement,
vous pourrez vous rendre compte que la plupart de nos tests pourront tre regroups
dans des blocs plus vastes, fonctions ou modules. Je vais dtailler tranquillement ces deux
concepts.

Les fonctions permettent de regrouper plusieurs instructions dans un bloc qui sera appel
grce un nom. Dailleurs, vous avez dj vu des fonctions : print et input en font partie
par exemple.
Les modules permettent de regrouper plusieurs fonctions selon le mme principe. Toutes
les fonctions mathmatiques, par exemple, peuvent tre places dans un module ddi aux
mathmatiques.

53

CHAPITRE 6. PAS PAS VERS LA MODULARIT (1/2)

Les fonctions : vous de jouer


Nous avons utilis pas mal de fonctions depuis le dbut de ce cours. On citera pour
mmoire print, type et input, sans compter quelques autres. Mais vous devez bien
vous rendre compte quil existe un nombre incalculable de fonctions dj construites
en Python. Toutefois, vous vous apercevrez aussi que, trs souvent, un programmeur
cre ses propres fonctions. Cest le premier pas que vous ferez, dans ce chapitre, vers la
modularit. Ce terme un peu barbare signifie que nous allons nous habituer regrouper dans des fonctions des parties de notre code que nous serons amens rutiliser.
Au prochain chapitre, nous apprendrons regrouper nos fonctions ayant un rapport
entre elles dans un fichier, pour constituer un module, mais nanticipons pas.

La cration de fonctions
Nous allons, pour illustrer cet exemple, reprendre le code de la table de multiplication,
que nous avons vu au chapitre prcdent et qui, dcidment, nen finit pas de vous
poursuivre.
Nous allons emprisonner notre code calculant la table de multiplication par 7 dans une
fonction que nous appellerons table_par_7.
On cre une fonction selon le schma suivant :
1
2

def n om _d e_la_fonction ( parametre1 , parametre2 , parametre3 ,


parametreN ) :
# Bloc d ' instructions

Les blocs dinstructions nous courent aprs aussi, quel enfer. Si lon dcortique la ligne
de dfinition de la fonction, on trouve dans lordre :
def, mot-cl qui est labrviation de define (dfinir, en anglais) et qui constitue
le prlude toute construction de fonction.
Le nom de la fonction, qui se nomme exactement comme une variable (nous verrons
par la suite que ce nest pas par hasard). Nutilisez pas un nom de variable dj
instancie pour nommer une fonction.
La liste des paramtres qui seront fournis lors dun appel la fonction. Les paramtres
sont spars par des virgules et la liste est encadre par des parenthses ouvrante et
fermante (l encore, les espaces sont optionnels mais amliorent la lisibilit).
Les deux points, encore et toujours, qui clturent la ligne.
Les parenthses sont obligatoires, quand bien mme votre fonction nattendrait aucun paramtre.
Le code pour mettre notre table de multiplication par 7 dans une fonction serait donc :
1
2
3

54

def table_par_7 () :
nb = 7
i = 0 # Notre compteur ! L ' auriez - vous oubli ?

LES FONCTIONS : VOUS DE JOUER


4
5
6

while i < 10 : # Tant que i est strictement inf rieure 10 ,


print ( i + 1 , " * " , nb , " = " , ( i + 1 ) * nb )
i += 1 # On incr mente i de 1 chaque tour de boucle .

Quand vous excutez ce code lcran, il ne se passe rien. Une fois que vous avez
retrouv les trois chevrons, essayez dappeler la fonction :
1
2
3
4
5
6
7
8
9
10
11
12

>>> table_par_7 ()
1 * 7 = 7
2 * 7 = 14
3 * 7 = 21
4 * 7 = 28
5 * 7 = 35
6 * 7 = 42
7 * 7 = 49
8 * 7 = 56
9 * 7 = 63
10 * 7 = 70
>>>

Bien, cest, euh, exactement ce quon avait russi faire au chapitre prcdent et
lintrt ne saute pas encore aux yeux. Lavantage est que lon peut appeler facilement
la fonction et rafficher toute la table sans avoir besoin de tout rcrire !
Mais, si on saisit des paramtres pour pouvoir afficher la table de 5 ou de
8. . . ?
Oui, ce serait dj bien plus utile. Je ne pense pas que vous ayez trop de mal trouver
le code de la fonction :
1
2
3
4
5

def table ( nb ) :
i = 0
while i < 10 : # Tant que i est strictement inf rieure 10 ,
print ( i + 1 , " * " , nb , " = " , ( i + 1 ) * nb )
i += 1 # On incr mente i de 1 chaque tour de boucle .

Et l, vous pouvez passer en argument diffrents nombres, table(8) pour afficher la


table de multiplication par 8 par exemple.
On peut aussi envisager de passer en paramtre le nombre de valeurs afficher dans la
table.
1
2
3
4
5

def table ( nb , max ) :


i = 0
while i < max : # Tant que i est strictement inf rieure la
variable max ,
print ( i + 1 , " * " , nb , " = " , ( i + 1 ) * nb )
i += 1

55

CHAPITRE 6. PAS PAS VERS LA MODULARIT (1/2)


Si vous tapez prsent table(11, 20), linterprteur vous affichera la table de 11, de
1*11 20*11. Magique non ?
Dans le cas o lon utilise plusieurs paramtres sans les nommer, comme
ici, il faut respecter lordre dappel des paramtres, cela va de soi. Si vous
commencez mettre le nombre daffichages en premier paramtre alors que,
dans la dfinition, ctait le second, vous risquez davoir quelques surprises.
Il est possible dappeler les paramtres dans le dsordre mais il faut, dans ce
cas, prciser leur nom : nous verrons cela plus loin.
Si vous fournissez en second paramtre un nombre ngatif, vous avez toutes les chances
de crer une magnifique boucle infinie. . . vous pouvez lempcher en rajoutant des
vrifications avant la boucle : par exemple, si le nombre est ngatif ou nul, je le mets 10.
En Python, on prfrera mettre un commentaire en tte de fonction ou une docstring,
comme on le verra ultrieurement, pour indiquer que max doit tre positif, plutt que
de faire des vrifications qui au final feront perdre du temps. Une des phrases refltant
la philosophie du langage et qui peut sappliquer ce type de situation est were all
consenting adults here 1 (sous-entendu, quelques avertissements en commentaires sont
plus efficaces quune restriction au niveau du code). On aura loccasion de retrouver
cette phrase plus loin, surtout quand on parlera des objets.

Valeurs par dfaut des paramtres


On peut galement prciser une valeur par dfaut pour les paramtres de la fonction.
Vous pouvez par exemple indiquer que le nombre maximum daffichages doit tre de
10 par dfaut (cest--dire si lutilisateur de votre fonction ne le prcise pas). Cela se
fait le plus simplement du monde :
1
2
3

def table ( nb , max = 10 ) :


""" Fonction affichant la table de multiplication par nb
de 1 * nb max * nb

4
5
6
7
8
9

( max >= 0 ) """


i = 0
while i < max :
print ( i + 1 , " * " , nb , " = " , ( i + 1 ) * nb )
i += 1

Il suffit de rajouter =10 aprs max. prsent, vous pouvez appeler la fonction de deux
faons : soit en prcisant le numro de la table et le nombre maximum daffichages, soit
en ne prcisant que le numro de la table (table(7)). Dans ce dernier cas, max vaudra
10 par dfaut.
Jen ai profit pour ajouter quelques lignes dexplications que vous aurez sans doute
remarques. Nous avons plac une chane de caractres, sans la capturer dans une
variable, juste en-dessous de la dfinition de la fonction. Cette chane est ce quon
1. Nous sommes entre adultes consentants .

56

LES FONCTIONS : VOUS DE JOUER


appelle une docstring que lon pourrait traduire par une chane daide. Si vous tapez
help(table), cest ce message que vous verrez apparatre. Documenter vos fonctions
est galement une bonne habitude prendre. Comme vous le voyez, on indente cette
chane et on la met entre triple guillemets. Si la chane figure sur une seule ligne, on
pourra mettre les trois guillemets fermants sur la mme ligne ; sinon, on prfrera sauter
une ligne avant de fermer cette chane, pour des raisons de lisibilit. Tout le texte daide
est indent au mme niveau que le code de la fonction.
Enfin, sachez que lon peut appeler des paramtres par leur nom. Cela est utile pour
une fonction comptant un certain nombre de paramtres qui ont tous une valeur par
dfaut. Vous pouvez aussi utiliser cette mthode sur une fonction sans paramtre par
dfaut, mais cest moins courant.
Prenons un exemple de dfinition de fonction :
1
2

def fonc ( a =1 , b =2 , c =3 , d =4 , e = 5 ) :
print ( " a = " , a , " b = " , b , " c = " , c , " d = " , d , " e = " , e )

Simple, nest-ce pas ? Eh bien, vous avez de nombreuses faons dappeler cette fonction.
En voici quelques exemples :
Instruction
fonc()
fonc(4)
fonc(b=8, d=5)
fonc(b=35, c=48, a=4, e=9)

Rsultat
a=1b=
a=4b=
a=1b=
a=4b=

2c=3d=4e=5
2c=3d=4e=5
8c=3d=5e=5
35 c = 48 d = 4 e = 9

Je ne pense pas que des explications supplmentaires simposent. Si vous voulez changer la valeur dun paramtre, vous tapez son nom, suivi dun signe gal puis dune
valeur (qui peut tre une variable bien entendu). Peu importent les paramtres que
vous prcisez (comme vous le voyez dans cet exemple o tous les paramtres ont une
valeur par dfaut, vous pouvez appeler la fonction sans paramtre), peu importe lordre
dappel des paramtres.

Signature dune fonction


On entend par signature de fonction les lments qui permettent au langage didentifier ladite fonction. En C++, par exemple, la signature dune fonction est constitue
de son nom et du type de chacun de ses paramtres. Cela veut dire que lon peut trouver plusieurs fonctions portant le mme nom mais dont les paramtres diffrent. Au
moment de lappel de fonction, le compilateur recherche la fonction qui sapplique
cette signature.
En Python comme vous avez pu le voir, on ne prcise pas les types des paramtres.
Dans ce langage, la signature dune fonction est tout simplement son nom. Cela signifie
que vous ne pouvez dfinir deux fonctions du mme nom (si vous le faites, lancienne
dfinition est crase par la nouvelle).
1

def exemple () :

57

CHAPITRE 6. PAS PAS VERS LA MODULARIT (1/2)


2

print ( " Un exemple d ' une fonction sans param tre " )

3
4

exemple ()

5
6
7

def exemple () : # On red finit la fonction exemple


print ( " Un autre exemple de fonction sans param tre " )

8
9

exemple ()

A la ligne 1 on dfinit la fonction exemple. On lappelle une premire fois la ligne


4. On redfinit la ligne 6 la fonction exemple. Lancienne dfinition est crase et
lancienne fonction ne pourra plus tre appele.
Retenez simplement que, comme pour les variables, un nom de fonction ne renvoie que
vers une fonction unique, on ne peut surcharger de fonctions en Python.

Linstruction return
Ce que nous avons fait tait intressant, mais nous navons pas encore fait le tour des
possibilits de la fonction. Et dailleurs, mme la fin de ce chapitre, il nous restera
quelques petites fonctionnalits voir. Si vous vous souvenez bien, il existe des fonctions
comme print qui ne renvoient rien (attention, renvoyer et afficher sont deux
choses diffrentes) et des fonctions telles que input ou type qui renvoient une valeur.
Vous pouvez capturer cette valeur en plaant une variable devant (exemple variable2
= type(variable1)). En effet, les fonctions travaillent en gnral sur des donnes et
renvoient le rsultat obtenu, suite un calcul par exemple.
Prenons un exemple simple : une fonction charge de mettre au carr une valeur passe
en argument. Je vous signale au passage que Python en est parfaitement capable sans
avoir coder une nouvelle fonction, mais cest pour lexemple.
1
2

def carre ( valeur ) :


return valeur * valeur

Linstruction return signifie quon va renvoyer 2 la valeur, pour pouvoir la rcuprer ensuite et la stocker dans une variable par exemple. Cette instruction arrte le
droulement de la fonction, le code situ aprs le return ne sexcutera pas.
1

variable = carre ( 5 )

La variable variable contiendra, aprs excution de cette instruction, 5 au carr, cest-dire 25.
Sachez que lon peut renvoyer plusieurs valeurs que lon spare par des virgules, et que
lon peut les capturer dans des variables galement spares par des virgules, mais je
mattarderai plus loin sur cette particularit. Retenez simplement la dfinition dune
fonction, les paramtres, les valeurs par dfaut, linstruction return et ce sera dj
bien.
2. Certains dentre vous ont peut-tre lhabitude demployer le mot retourner ; il sagit dun
anglicisme et je lui prfre lexpression renvoyer .

58

LES FONCTIONS LAMBDA

Les fonctions lambda


Nous venons de voir comment crer une fonction grce au mot-cl def. Python nous
propose un autre moyen de crer des fonctions, des fonctions extrmement courtes car
limites une seule instruction.
Pourquoi une autre faon de crer des fonctions ? La premire suffit, non ?

Disons que ce nest pas tout fait la mme chose, comme vous allez le voir. Les
fonctions lambda sont en gnral utilises dans un certain contexte, pour lequel dfinir
une fonction laide de def serait plus long et moins pratique.

Syntaxe
Avant tout, voyons la syntaxe dune dfinition de fonction lambda. Nous allons utiliser
le mot-cl lambda comme ceci : lambda arg1, arg2,... : instruction de retour.
Je pense quun exemple vous semblera plus clair. On veut crer une fonction qui prend
un paramtre et renvoie ce paramtre au carr.
1
2
3

>>> lambda x : x * x
< function < lambda > at 0 x00BA1B70 >
>>>

Dabord, on a le mot-cl lambda suivi de la liste des arguments, spars par des virgules.
Ici, il ny a quun seul argument, cest x. Ensuite figure un nouveau signe deux points
: et linstruction de la lambda. Cest le rsultat de linstruction que vous placez ici
qui sera renvoy par la fonction. Dans notre exemple, on renvoie donc x * x.
Comment fait-on pour appeler notre lambda ?

On a bien cr une fonction lambda mais on ne dispose ici daucun moyen pour lappeler.
Vous pouvez tout simplement stocker votre fonction lambda nouvellement dfinie dans
une variable, par une simple affectation :
1
2
3
4
5
6

>>> f = lambda x : x * x
>>> f (5)
25
>>> f ( -18)
324
>>>

59

CHAPITRE 6. PAS PAS VERS LA MODULARIT (1/2)


Un autre exemple : si vous voulez crer une fonction lambda prenant deux paramtres
et renvoyant la somme de ces deux paramtres, la syntaxe sera la suivante :
1

lambda x , y : x + y

Utilisation
notre niveau, les fonctions lambda sont plus une curiosit que vritablement utiles.
Je vous les prsente maintenant parce que le contexte sy prte et que vous pourriez
en rencontrer certaines sans comprendre ce que cest.
Il vous faudra cependant attendre un peu pour que je vous montre une relle application
des lambda. En attendant, noubliez pas ce mot-cl et la syntaxe qui va avec. . . on passe
la suite !

la dcouverte des modules


Jusquici, nous avons travaill avec les fonctions de Python charges au lancement de
linterprteur. Il y en a dj un certain nombre et nous pourrions continuer et finir
cette premire partie sans utiliser de module Python. . . ou presque. Mais il faut bien
qu un moment, je vous montre cette possibilit des plus intressantes !

Les modules, quest-ce que cest ?


Un module est grossirement un bout de code que lon a enferm dans un fichier. On
emprisonne ainsi des fonctions et des variables ayant toutes un rapport entre elles.
Ainsi, si lon veut travailler avec les fonctionnalits prvues par le module (celles qui
ont t enfermes dans le module), il ny a qu importer le module et utiliser ensuite
toutes les fonctions et variables prvues.
Il existe un grand nombre de modules disponibles avec Python sans quil soit ncessaire dinstaller des bibliothques supplmentaires. Pour cette partie, nous prendrons
lexemple du module math qui contient, comme son nom lindique, des fonctions mathmatiques. Inutile de vous inquiter, nous nallons pas nous attarder sur le module
lui-mme pour coder une calculatrice scientifique, nous verrons surtout les diffrentes
mthodes dimportation.

La mthode import
Lorsque vous ouvrez linterprteur Python, les fonctionnalits du module math ne sont
pas incluses. Il sagit en effet dun module, il vous appartient de limporter si vous vous
dites tiens, mon programme risque davoir besoin de fonctions mathmatiques . Nous
allons voir une premire syntaxe dimportation.
1

60

>>> import math

LA DCOUVERTE DES MODULES


2

>>>

La syntaxe est facile retenir : le mot-cl import, qui signifie importer en anglais,
suivi du nom du module, ici math.
Aprs lexcution de cette instruction, rien ne se passe. . . en apparence. En ralit,
Python vient dimporter le module math. Toutes les fonctions mathmatiques contenues
dans ce module sont maintenant accessibles. Pour appeler une fonction du module, il
faut taper le nom du module suivi dun point . puis du nom de la fonction. Cest
la mme syntaxe pour appeler des variables du module. Voyons un exemple :
1
2
3

>>> math . sqrt (16)


4
>>>

Comme vous le voyez, la fonction sqrt du module math renvoie la racine carre du
nombre pass en paramtre.
Mais comment suis-je cens savoir quelles fonctions existent et ce que fait
math.sqrt dans ce cas prcis ?
Jaurais d vous montrer cette fonction bien plus tt car, oui, cest une fonction qui
va nous donner la solution. Il sagit de help, qui prend en argument la fonction ou le
module sur lequel vous demandez de laide. Laide est fournie en anglais mais cest de
langlais technique, cest--dire une forme de langlais que vous devrez matriser pour
programmer, si ce nest pas dj le cas. Une grande majorit de la documentation est
en anglais, bien que vous puissiez maintenant en trouver une bonne part en franais.
1
2

>>> help (" math ")


Help on built - in module math :

3
4

NAME

math

6
7
8

FILE

( built - in )

9
10
11
12

DESCRIPTION
This module is always available . It provides access to the
mathematical functions defined by the C standard .

13
14
15
16

FUNCTIONS
acos ( ... )
acos ( x )

17
18

Return the arc cosine ( measured in radians ) of x .

19
20

acosh ( ... )

61

CHAPITRE 6. PAS PAS VERS LA MODULARIT (1/2)


acosh ( x )

21
22

Return the hyperbolic arc cosine ( measured in radians )


of x .

23
24
25
26

asin ( ... )
-- Suite --

Si vous parlez un minimum langlais, vous avez accs une description exhaustive des
fonctions du module math. Vous voyez en haut de la page le nom du module, le fichier
qui lhberge, puis la description du module. Ensuite se trouve une liste des fonctions,
chacune tant accompagne dune courte description.



Tapez Q pour revenir la fentre dinterprteur, Espace pour avancer dune page,



Entre pour avancer dune ligne. Vous pouvez galement passer un nom de fonction
en paramtre de la fonction help.
1
2

>>> help (" math . sqrt ")


Help on built - in function sqrt in module math :

3
4
5

sqrt ( ... )
sqrt ( x )

Return the square root of x .

7
8
9

>>>

Ne mettez pas les parenthses habituelles aprs le nom de la fonction. Cest en


ralit la rfrence de la fonction que vous envoyez help. Si vous rajoutez les
parenthses ouvrantes et fermantes aprs le nom de la fonction, vous devrez
prciser une valeur. Dans ce cas, cest la valeur renvoye par math.sqrt qui
sera analyse, soit un nombre (entier ou flottant).
Nous reviendrons plus tard sur le concept des rfrences des fonctions. Si vous avez
compris pourquoi il ne fallait pas mettre de parenthses aprs le nom de la fonction
dans help, tant mieux. Sinon, ce nest pas grave, nous y reviendrons en temps voulu.

Utiliser un espace de noms spcifique


En vrit, quand vous tapez import math, cela cre un espace de noms dnomm
math , contenant les variables et fonctions du module math. Quand vous tapez
math.sqrt(25), vous prcisez Python que vous souhaitez excuter la fonction sqrt
contenue dans lespace de noms math. Cela signifie que vous pouvez avoir, dans lespace
de noms principal, une autre fonction sqrt que vous avez dfinie vous-mmes. Il ny
aura pas de conflit entre, dune part, la fonction que vous avez cre et que vous
appellerez grce linstruction sqrt et, dautre part, la fonction sqrt du module math
62

LA DCOUVERTE DES MODULES


que vous appellerez grce linstruction math.sqrt.
Mais, concrtement, un espace de noms, cest quoi ?

Il sagit de regrouper certaines fonctions et variables sous un prfixe spcifique. Prenons


un exemple concret :
1
2
3

import math
a = 5
b = 33 . 2

Dans lespace de noms principal, celui qui ne ncessite pas de prfixe et que vous utilisez
depuis le dbut de ce cours, on trouve :
La variable a.
La variable b.
Le module math, qui se trouve dans un espace de noms sappelant math galement.
Dans cet espace de noms, on trouve :
la fonction sqrt ;
la variable pi ;
et bien dautres fonctions et variables. . .
Cest aussi lintrt des modules : des variables et fonctions sont stockes part, bien
labri dans un espace de noms, sans risque de conflit avec vos propres variables et
fonctions. Mais dans certains cas, vous pourrez vouloir changer le nom de lespace de
noms dans lequel sera stock le module import.
1
2

import math as mathematiques


mathematiques . sqrt ( 25 )

Quest-ce quon a fait l ?

On a simplement import le module math en spcifiant Python de lhberger dans


lespace de noms dnomm mathematiques au lieu de math. Cela permet de mieux
contrler les espaces de noms des modules que vous importerez. Dans la plupart des
cas, vous nutiliserez pas cette fonctionnalit mais, au moins, vous savez quelle existe.
Quand on se penchera sur les packages, vous vous souviendrez probablement de cette
possibilit.

Une autre mthode dimportation : from ... import ...


Il existe une autre mthode dimportation qui ne fonctionne pas tout fait de la mme
faon. En fonction du rsultat attendu, jutilise indiffremment lune ou lautre de
ces mthodes. Reprenons notre exemple du module math. Admettons que nous ayons
63

CHAPITRE 6. PAS PAS VERS LA MODULARIT (1/2)


uniquement besoin, dans notre programme, de la fonction renvoyant la valeur absolue
dune variable. Dans ce cas, nous nallons importer que la fonction, au lieu dimporter
tout le module.
1
2
3
4
5
6

>>> from math import fabs


>>> fabs ( -5)
5
>>> fabs (2)
2
>>>

Pour ceux qui nont pas encore tudi les valeurs absolues, il sagit tout simplement de
loppos de la variable si elle est ngative, et de la variable elle-mme si elle est positive.
Une valeur absolue est ainsi toujours positive.
Vous aurez remarqu quon ne met plus le prfixe math. devant le nom de la fonction. En
effet, nous lavons importe avec la mthode from : celle-ci charge la fonction depuis le
module indiqu et la place dans linterprteur au mme plan que les fonctions existantes,
comme print par exemple. Si vous avez compris les explications sur les espaces de noms,
vous voyez que print et fabs sont dans le mme espace de noms (principal).
Vous pouvez appeler toutes les variables et fonctions dun module en tapant * la
place du nom de la fonction importer.
1
2
3
4
5

>>> from math import *


>>> sqrt (4)
2
>>> fabs (5)
5

la ligne 1 de notre programme, linterprteur a parcouru toutes les fonctions et


variables du module math et les a importes directement dans lespace de noms principal
sans les emprisonner dans lespace de noms math.

Bilan
Quelle mthode faut-il utiliser ?

Vaste question ! Je dirais que cest vous de voir. La seconde mthode a lavantage
inestimable dconomiser la saisie systmatique du nom du module en prfixe de chaque
fonction. Linconvnient de cette mthode apparat si lon utilise plusieurs modules de
cette manire : si par hasard il existe dans deux modules diffrents deux fonctions
portant le mme nom, linterprteur ne conservera que la dernire fonction appele 3 .
Conclusion. . . cest vous de voir en fonction de vos besoins !
3. Je vous rappelle quil ne peut y avoir deux variables ou fonctions portant le mme nom.

64

LA DCOUVERTE DES MODULES

En rsum
Une fonction est une portion de code contenant des instructions, que lon va pouvoir
rutiliser facilement.
Dcouper son programme en fonctions permet une meilleure organisation.
Les fonctions peuvent recevoir des informations en entre et renvoyer une information
grce au mot-cl return.
Les fonctions se dfinissent de la faon suivante : def nom_fonction(parametre1,
parametre2, parametreN):

65

CHAPITRE 6. PAS PAS VERS LA MODULARIT (1/2)

66

Chapitre

Pas pas vers la modularit (2/2)


Difficult :
ous allons commencer par voir comment mettre nos programmes en bote. . . ou plutt
en fichier. Je vais faire dune pierre deux coups : dabord, cest chouette davoir son
programme dans un fichier modifiable souhait, surtout quon commence pouvoir
faire des programmes assez sympas (mme si vous nen avez peut-tre pas limpression).
Ensuite, cest un prlude ncessaire la cration de modules.

Comme vous allez le voir, nos programmes Python peuvent tre mis dans des fichiers pour
tre excuts ultrieurement. De ce fait, vous avez dj pratiquement toutes les cls pour
crer un programme Python excutable. Le mme mcanisme est utilis pour la cration
de modules. Les modules sont eux aussi des fichiers contenant du code Python.
Enfin, nous verrons la fin de ce chapitre comment crer des packages pour regrouper
nos modules ayant un rapport entre eux.
Cest parti !

67

CHAPITRE 7. PAS PAS VERS LA MODULARIT (2/2)

Mettre en bote notre code


Fini, linterprteur ?
Je le rpte encore, linterprteur est vritablement trs pratique pour un grand nombre
de raisons. Et la meilleure dentre elles est quil propose une manire interactive dcrire
un programme, qui permet de tester le rsultat de chaque instruction. Toutefois, linterprteur a aussi un dfaut : le code que vous saisissez est effac la fermeture de la
fentre. Or, nous commenons tre capables de rdiger des programmes relativement
complexes, mme si vous ne vous en rendez pas encore compte. Dans ces conditions,
devoir rcrire le code entier de son programme chaque fois quon ouvre linterprteur
de commandes est assez lourd.
La solution ? Mettre notre code dans un fichier que nous pourrons lancer volont,
comme un vritable programme !
Comme je lai dit au dbut de ce chapitre, il est grand temps que je vous prsente cette
possibilit. Mais on ne dit pas adieu linterprteur de commandes pour autant. On
lui dit juste au revoir pour cette fois. . . on le retrouvera bien assez tt, la possibilit de
tester le code la vole est vraiment un atout pour apprendre le langage.

Emprisonnons notre programme dans un fichier


Pour cette dmonstration, je reprendrai le code optimis du programme calculant si
une anne est bissextile. Cest un petit programme dont lutilit est certes discutable
mais il remplit un but prcis, en loccurrence dire si lanne saisie par lutilisateur est
bissextile ou non : cela suffit pour un premier essai.
Je vous remets le code ici pour que nous travaillions tous sur les mmes lignes, mme
si votre version fonctionnera galement sans problme dans un fichier, si elle tournait
sous linterprteur de commandes.
1

# Programme testant si une ann e , saisie par l ' utilisateur , est


bissextile ou non

2
3
4

annee = input ( " Saisissez une ann e : " ) # On attend que l '
utilisateur fournisse l ' ann e qu ' il d sire tester
annee = int ( annee ) # Risque d ' erreur si l ' utilisateur n 'a pas
saisi un nombre

5
6
7
8
9

if annee % 400 == 0 or ( annee % 4 == 0 and annee % 100 != 0 ) :


print ( " L ' ann e saisie est bissextile . " )
else :
print ( " L ' ann e saisie n ' est pas bissextile . " )


Copier ce code
B
Code web : 886842


Cest votre tour de travailler maintenant, je vais vous donner des pistes mais je ne vais
pas me mettre votre place, chacun prend ses habitudes en fonction de ses prfrences.
68

METTRE EN BOTE NOTRE CODE


Ouvrez un diteur basique : sous Windows, le bloc-notes est candidat, Wordpad ou
Word sont exclus ; sous Linux, vous pouvez utiliser Vim ou Emacs. Insrez le code
dans ce fichier et enregistrez-le avec lextension .py (exemple bissextile.py), comme
la figure 7.1. Cela permettra au systme dexploitation de savoir quil doit utiliser
Python pour excuter ce programme 1 .

Figure 7.1 Enregistrer un fichier Python sous Windows


Sous Linux, vous devrez ajouter dans votre fichier une ligne, tout au dbut, spcifiant
le chemin de linterprteur Python (si vous avez dj rdig des scripts, en bash par
exemple, cette mthode ne vous surprendra pas). La premire ligne de votre programme
sera :
1

# ! chemin

Remplacez alors le terme chemin par le chemin donnant accs linterprteur, par
exemple : /usr/bin/python3.4. Vous devrez changer le droit dexcution du fichier
avant de lexcuter comme un script.
Sous Windows, rendez-vous dans le dossier o vous avez enregistr votre fichier .py.
Vous pouvez faire un double-clic dessus, Windows saura quil doit appeler Python grce
lextension .py et Python reprend la main. Attendez toutefois car il reste quelques
petites choses rgler avant de pouvoir excuter votre programme.
1. Cela est ncessaire sous Windows uniquement.

69

CHAPITRE 7. PAS PAS VERS LA MODULARIT (2/2)

Quelques ajustements
Quand on excute un programme directement dans un fichier et que le programme
contient des accents (et cest le cas ici), il est ncessaire de prciser Python lencodage
de ces accents. Je ne vais pas rentrer dans les dtails, je vais simplement vous donner
une ligne de code quil faudra placer tout en haut de votre programme (sous Linux,
cette ligne doit figurer juste en-dessous du chemin de linterprteur Python).
1

# -* - coding : ENCODAGE -*

Sous Windows, vous devrez probablement remplacer ENCODAGE par Latin-1 . Sous
Linux, ce sera plus vraissemblablement utf-8 . Ce nest pas le lieu, ni le moment,
pour un cours sur les encodages. Utilisez simplement la ligne qui marche chez vous et
tout ira bien.
Il est probable, si vous excutez votre application dun double-clic, que votre programme
se referme immdiatement aprs vous avoir demand lanne. En ralit, il fait bel et
bien le calcul mais il arrive la fin du programme en une fraction de seconde et referme
lapplication, puisquelle est finie. Pour pallier cette difficult, il faut demander votre
programme de se mettre en pause la fin de son excution. Vous devrez rajouter
une instruction un peu spciale, un appel systme qui marche sous Windows (pas
sous Linux). Il faut tout dabord importer le module os. Ensuite, on rajoute lappel
la fonction os.system en lui passant en paramtre la chane de caractres pause
(cela, la fin de votre programme). Sous Linux, vous pouvez simplement excuter votre
programme dans la console ou, si vous tenez faire une pause, utilisez par exemple
input avant la fin de votre programme (pas bien lgant toutefois).
1

# -* - coding : Latin - 1 -*

2
3
4
5

import os # On importe le module os qui dispose de variables


# et de fonctions utiles pour dialoguer avec votre
# syst me d ' exploitation

6
7

# Programme testant si une ann e , saisie par l ' utilisateur , est


bissextile ou non

8
9
10

annee = input ( " Saisissez une ann e : " ) # On attend que l '
utilisateur fournisse l ' ann e qu ' il d sire tester
annee = int ( annee ) # Risque d ' erreur si l ' utilisateur n 'a pas
saisi un nombre

11
12
13
14
15

if annee % 400 == 0 or ( annee % 4 == 0 and annee % 100 != 0 ) :


print ( " L ' ann e saisie est bissextile . " )
else :
print ( " L ' ann e saisie n ' est pas bissextile . " )

16
17
18

70

# On met le programme en pause pour viter qu ' il ne se referme


( Windows )
os . system ( " pause " )

JE VIENS POUR CONQURIR LE MONDE. . . ET CRER MES PROPRES


MODULES
Vous pouvez dsormais ouvrir votre fichier bissextile.py, le programme devrait fonctionner parfaitement (figure 7.2).

Figure 7.2 Notre programme ne se ferme plus !


Quand vous excutez ce script, que ce soit sous Windows ou Linux, vous faites
toujours appel linterprteur Python ! Votre programme nest pas compil
mais chaque ligne dinstruction est excute la vole par linterprteur, le
mme qui excutait vos premiers programmes dans linterprteur de commandes. La grande diffrence ici est que Python excute votre programme
depuis le fichier et que donc, si vous souhaitez modifier le programme, il
faudra modifier le fichier.
Sachez quil existe des diteurs spcialiss pour Python, notamment Idle qui est install
en mme temps que Python (personnellement je ne lutilise pas). Vous pouvez louvrir
avec un clic droit sur votre fichier .py et regarder comment il fonctionne, ce nest pas
bien compliqu et vous pouvez mme excuter votre programme depuis ce logiciel. Mais,
tant donn que je ne lutilise pas, je ne vous ferai pas un cours dessus. Si vous avez
du mal utiliser une des fonctionnalits du logiciel, recherchez sur Internet : dautres
cours doivent exister, en anglais dans le pire des cas.

Je viens pour conqurir le monde. . . et crer mes propres


modules
Mes modules moi
Bon, nous avons vu le plus dur. . . a va ? Rassurez-vous, nous nallons rien faire de
compliqu dans cette dernire section. Le plus dur est derrire nous.
Commencez par vous crer un espace de test pour les petits programmes Python que
nous allons tre amens crer, un joli dossier lcart de vos photos et musiques.
71

CHAPITRE 7. PAS PAS VERS LA MODULARIT (2/2)


Nous allons crer deux fichiers .py dans ce dossier :
un fichier multipli.py, qui contiendra la fonction table que nous avons code au
chapitre prcdent ;
un fichier test.py, qui contiendra le test dexcution de notre module.
Vous devriez vous en tirer sans problme. Noubliez pas de spcifier la ligne prcisant lencodage en tte de vos deux fichiers. Maintenant, voyons le code du fichier
multipli.py.
1

""" module multipli contenant la fonction table """

2
3
4
5
6
7
8
9

def table ( nb , max = 10 ) :


""" Fonction affichant la table de multiplication par nb de
1 * nb jusqu ' max * nb """
i = 0
while i < max :
print ( i + 1 , " * " , nb , " = " , ( i + 1 ) * nb )
i += 1

On se contente de dfinir une seule fonction, table, qui affiche la table de multiplication
choisie. Rien de nouveau jusquici. Si vous vous souvenez des docstrings, dont nous
avons parl au chapitre prcdent, vous voyez que nous en avons insr une nouvelle
ici, non pas pour commenter une fonction mais bien un module entier. Cest une bonne
habitude prendre quand nos projets deviennent importants.
Voici le code du fichier test.py, noubliez pas la ligne prcisant votre encodage, en
tte du fichier.
1
2

import os
from multipli import *

3
4
5
6

# test de la fonction table


table (3 , 20 )
os . system ( " pause " )

En le lanant directement, voil ce quon obtient :


1
2
3
4
5
6
7
8
9
10
11
12
13
14

72

1 * 3 = 3
2 * 3 = 6
3 * 3 = 9
4 * 3 = 12
5 * 3 = 15
6 * 3 = 18
7 * 3 = 21
8 * 3 = 24
9 * 3 = 27
10 * 3 = 30
11 * 3 = 33
12 * 3 = 36
13 * 3 = 39
14 * 3 = 42

JE VIENS POUR CONQURIR LE MONDE. . . ET CRER MES PROPRES


MODULES
15
16
17
18
19
20
21

15 * 3 = 45
16 * 3 = 48
17 * 3 = 51
18 * 3 = 54
19 * 3 = 57
20 * 3 = 60
Appuyez sur une touche pour continuer ...

Je ne pense pas avoir grand chose ajouter. Nous avons vu comment crer un module,
il suffit de le mettre dans un fichier. On peut alors limporter depuis un autre fichier
contenu dans le mme rpertoire en prcisant le nom du fichier (sans lextension .py).
Notre code, encore une fois, nest pas trs utile mais vous pouvez le modifier pour le
rendre plus intressant, vous en avez parfaitement les comptences prsent.
Au moment dimporter votre module, Python va lire (ou crer si il nexiste pas) un
fichier .pyc. partir de la version 3.2, ce fichier se trouve dans un dossier __pycache__.
Ce fichier est gnr par Python et contient le code compil (ou presque) de votre
module. Il ne sagit pas rellement de langage machine mais dun format que Python
dcode un peu plus vite que le code que vous pouvez crire. Python se charge lui-mme
de gnrer ce fichier et vous navez pas vraiment besoin de vous en soucier quand vous
codez, simplement ne soyez pas surpris.

Faire un test de module dans le module-mme


Dans lexemple que nous venons de voir, nous avons cr deux fichiers, le premier
contenant un module, le second testant ledit module. Mais on peut trs facilement tester
le code dun module dans le module mme. Cela veut dire que vous pourriez excuter
votre module comme un programme lui tout seul, un programme qui testerait le
module crit dans le mme fichier. Voyons voir cela.
Reprenons le code du module multipli :
1

""" module multipli contenant la fonction table """

2
3
4
5
6
7
8
9

def table ( nb , max = 10 ) :


""" Fonction affichant la table de multiplication par nb de
1 * nb jusqu ' max * nb """
i = 0
while i < max :
print ( i + 1 , " * " , nb , " = " , ( i + 1 ) * nb )
i += 1

Ce module dfinit une seule fonction, table, quil pourrait tre bon de tester. Oui
mais. . . si nous rajoutons juste en dessous une ligne, par exemple table(8), cette ligne
sera excute lors de limportation et donc, dans le programme appelant le module.
Quand vous ferez import multipli, vous verrez la table de multiplication par 8 safficher. . . hum, il y a mieux.
Heureusement, il y a un moyen trs rapide de sparer les lments du code qui doivent
73

CHAPITRE 7. PAS PAS VERS LA MODULARIT (2/2)


tre excuts lorsquon lance le module directement en tant que programme ou lorsquon
cherche limporter. Voici le code de la solution, les explications suivent :
1

""" module multipli contenant la fonction table """

2
3

import os

4
5
6
7
8
9
10
11

def table ( nb , max = 10 ) :


""" Fonction affichant la table de multiplication par nb de
1 * nb jusqu ' max * nb """
i = 0
while i < max :
print ( i + 1 , " * " , nb , " = " , ( i + 1 ) * nb )
i += 1

12
13
14
15
16

# test de la fonction table


if __name__ == " __main__ " :
table ( 4 )
os . system ( " pause " )

Noubliez pas la ligne indiquant lencodage !

Voil. prsent, si vous faites un double-clic directement sur le fichier multipli.py,


vous allez voir la table de multiplication par 4. En revanche, si vous limportez, le
code de test ne sexcutera pas. Tout repose en fait sur la variable __name__, cest
une variable qui existe ds le lancement de linterprteur. Si elle vaut __main__, cela
veut dire que le fichier appel est le fichier excut. Autrement dit, si __name__ vaut
__main__, vous pouvez mettre un code qui sera excut si le fichier est lanc directement
comme un excutable.
Prenez le temps de comprendre ce mcanisme, faites des tests si ncessaire, cela pourra
vous tre utile par la suite.

Les packages
Les modules sont un des moyens de regrouper plusieurs fonctions (et, comme on le verra
plus tard, certaines classes galement). On peut aller encore au-del en regroupant des
modules dans ce quon va appeler des packages.

En thorie
Comme je lai dit, un package sert regrouper plusieurs modules. Cela permet de ranger
plus proprement vos modules, classes et fonctions dans des emplacements spars. Si
vous voulez y accder, vous allez devoir fournir un chemin vers le module que vous
74

LES PACKAGES
visez. De ce fait, les risques de conflits de noms sont moins importants et surtout, tout
est bien plus ordonn.
Par exemple, imaginons que vous installiez un jour une bibliothque tierce pour crire
une interface graphique. En sinstallant, la bibliothque ne va pas crer ses dizaines
(voire ses centaines) de modules au mme endroit. Ce serait un peu dsordonn. . .
surtout quand on pense quon peut ranger tout cela dune faon plus claire : dun ct,
on peut avoir les diffrents objets graphiques de la fentre, de lautres les diffrents
vnements (clavier, souris,. . .), ailleurs encore les effets graphiques. . .
Dans ce cas, on va srement se retrouver face un package portant le nom de la bibliothque. Dans ce package se trouveront probablement dautres packages, un nomm
evenements, un autre objets, un autre encore effets. Dans chacun de ces packages,
on pourra trouver soit dautres packages, soit des modules et dans chacun de ces modules, des fonctions.
Ouf ! Cela nous fait une hirarchie assez complexe non ? Dun autre ct, cest tout
lintrt. Concrtement, pour utiliser cette bibliothque, on nest pas oblig de connatre
tous ses packages, modules et fonctions (heureusement dailleurs !) mais juste ceux dont
on a rellement besoin.

En pratique
En pratique, les packages sont. . . des rpertoires ! Dedans peuvent se trouver dautres
rpertoires (dautres packages) ou des fichiers (des modules).
Exemple de hirarchie
Pour notre bibliothque imaginaire, la hirarchie des rpertoires et fichiers ressemblerait
cela :
Un rpertoire du nom de la bibliothque contenant :
un rpertoire evenements contenant :
un module clavier ;
un module souris ;
...
un rpertoire effets contenant diffrents effets graphiques ;
un rpertoire objets contenant les diffrents objets graphiques de notre fentre
(boutons, zones de texte, barres de menus. . .).
Importer des packages
Si vous voulez utiliser, dans votre programme, la bibliothque fictive que nous venons
de voir, vous avez plusieurs moyens qui tournent tous autour des mots-cls from et
import :
1

import nom_bibliotheque

75

CHAPITRE 7. PAS PAS VERS LA MODULARIT (2/2)


Cette ligne importe le package contenant la bibliothque. Pour accder aux souspackages, vous utiliserez un point . afin de modliser le chemin menant au module
ou la fonction que vous voulez utiliser :
1
2

nom_bibliotheque . evenements # Pointe vers le sous - package


evenements
nom_bibliotheque . evenements . clavier # Pointe vers le module
clavier

Si vous ne voulez importer quun seul module (ou quune seule fonction) dun package,
vous utiliserez une syntaxe similaire, assez intuitive :
1

from nom_bibliotheque . objets import bouton

En fonction des besoins, vous pouvez dcider dimporter tout un package, un souspackage, un sous-sous-package. . . ou bien juste un module ou mme une seule fonction.
Cela dpendra de vos besoins.
Crer ses propres packages
Si vous voulez crer vos propres packages, commencez par crer, dans le mme dossier
que votre programme Python, un rpertoire portant le nom du package.
Dans ce rpertoire, vous pouvez soit :
mettre vos modules, vos fichiers lextension .py ;
crer des sous-packages de la mme faon, en crant un rpertoire dans votre package.
Ne mettez pas despaces dans vos noms de packages et vitez aussi les caractres spciaux. Quand vous les utilisez dans vos programmes, ces noms sont
traits comme des noms de variables et ils doivent donc obir aux mmes
rgles de nommage.

Le fichier dinitialisation
En Python, vous trouverez souvent le fichier dinitialisation de package __init__.py
dans un rpertoire destin devenir un package. Ce fichier est optionnel depuis la
version 3.3 de Python. Vous ntes pas oblig de le crer mais vous pouvez y mettre du
code dinitialisation pour votre package. Je ne vais pas rentrer dans le dtail ici (vous
avez dj beaucoup de choses retenir), mais sachez que ce code dinitialisation est
appel quand vous importez votre package.
Un dernier exemple
Voici un dernier exemple, que vous pouvez cette fois faire en mme temps que moi pour
vous assurer que cela fonctionne.
76

LES PACKAGES
Dans votre rpertoire de code, l o vous mettez vos exemples Python, crez un fichier
.py que vous appelerez test_package.py.
Crez dans le mme rpertoire un dossier package. Dedans, crez un fichier fonctions.py
dans lequel vous recopierez votre fonction table.
Dans votre fichier test_package.py, si vous voulez importer votre fonction table,
vous avez plusieurs solutions :
1
2

from package . fonctions import table


table ( 5 ) # Appel de la fonction table

3
4
5
6

# Ou ...
import package . fonctions
fonctions . table ( 5 ) # Appel de la fonction table

Voil. Il reste bien des choses dire sur les packages mais je crois que vous avez vu lessentiel. Cette petite explication rvlera son importance quand vous aurez construire
des programmes assez volumineux. vitez de tout mettre dans un seul module sans
chercher hirarchiser, profitez de cette possibilit offerte par Python.

En rsum
On peut crire les programmes Python dans des fichiers portant lextension .py.
On peut crer des fichiers contenant des modules pour sparer le code.
On peut crer des rpertoires contenant des packages pour hirarchiser un programme.

77

CHAPITRE 7. PAS PAS VERS LA MODULARIT (2/2)

78

Chapitre

Les exceptions
Difficult :

ans ce chapitre, nous aborderons le dernier concept que je considre comme indispensable avant dattaquer la partie sur la Programmation Oriente Objet, jai nomm
les exceptions .

Comme vous allez le voir, il sagit des erreurs que peut rencontrer Python en excutant
votre programme. Ces erreurs peuvent tre interceptes trs facilement et cest mme, dans
certains cas, indispensable.
Cependant, il ne faut pas tout intercepter non plus : si Python envoie une erreur, cest quil
y a une raison. Si vous ignorez une erreur, vous risquez davoir des rsultats trs tranges
dans votre programme.

79

CHAPITRE 8. LES EXCEPTIONS

quoi cela sert-il ?


Nous avons dj t confronts des erreurs dans nos programmes, certaines que jai
volontairement provoques, mais la plupart que vous avez d rencontrer si vous avez
test un minimum des instructions dans linterprteur. Quand Python rencontre une
erreur dans votre code, il lve une exception. Sans le savoir, vous avez donc dj vu
des exceptions leves par Python :
1
2
3
4
5

>>> # Exemple classique : test d une division par z ro


>>> variable = 1/0
Traceback ( most recent call last ) :
File " < stdin >" , line 1 , in < module >
ZeroD ivisionError : int division or modulo by zero

Attardons-nous sur la dernire ligne. Nous y trouvons deux informations :


ZeroDivisionError : le type de lexception ;
int division or modulo by zero : le message quenvoie Python pour vous aider
comprendre lerreur qui vient de se produire.
Python lve donc des exceptions quand il trouve une erreur, soit dans le code (une
erreur de syntaxe, par exemple), soit dans lopration que vous lui demandez de faire.
Notez qu linstar des variables, on trouve diffrents types dexceptions que Python
va utiliser en fonction de la situation. Le type dexception ValueError, notamment,
pourra tre lev par Python face diverses erreurs de valeurs . Dans ce cas, cest
donc le message qui vous indique plus clairement le problme. Nous verrons dans la
prochaine partie, consacre la Programmation Oriente Objet, ce que sont rellement
ces types dexceptions.
Bon, cest bien joli davoir cette exception. On voit le fichier et la ligne laquelle sest
produite lerreur (trs pratique quand on commence travailler sur un projet) et on
a une indication sur le problme qui suffit en gnral le rgler. Mais Python permet
quelque chose de bien plus pratique.
Admettons que certaines erreurs puissent tre provoques par lutilisateur. Par exemple,
on demande lutilisateur de saisir au clavier un entier et il tape une chane de caractres. . . problme. Nous avons dj rencontr cette situation : souvenez-vous du
programme bissextile.
1
2

annee = input () # On demande l ' utilisateur de saisir l ' ann e


annee = int ( annee ) # On essaye de convertir l ' ann e en un
entier

Je vous avais dit que si lutilisateur fournissait ici une valeur impossible convertir en
entier (une lettre par exemple), le programme plantait. En fait, il lve une exception
et Python arrte lexcution du programme. Si vous testez le programme en faisant
un double-clic directement dans lexplorateur, il va se fermer tout de suite (en fait, il
affiche bel et bien lerreur mais se referme aussitt).
80

FORME MINIMALE DU BLOC TRY


Dans ce cas, et dans dautres cas similaires, Python permet de tester un extrait de code.
Sil ne renvoie aucune erreur, Python continue. Sinon, on peut lui demander dexcuter
une autre action (par exemple, redemander lutilisateur de saisir lanne). Cest ce
que nous allons voir ici.

Forme minimale du bloc try


On va parler ici de bloc try. Nous allons en effet mettre les instructions que nous
souhaitons tester dans un premier bloc et les instructions excuter en cas derreur
dans un autre bloc. Sans plus attendre, voici la syntaxe :
1
2
3
4

try :

# Bloc essayer
except :
# Bloc qui sera ex cut en cas d ' erreur

Dans lordre, nous trouvons :


Le mot-cl try suivi des deux points : (try signifie essayer en anglais).
Le bloc dinstructions essayer.
Le mot-cl except suivi, une fois encore, des deux points : . Il se trouve au mme
niveau dindentation que le try.
Le bloc dinstructions qui sera excut si une erreur est trouve dans le premier bloc.
Reprenons notre test de conversion en enfermant dans un bloc try linstruction susceptible de lever une exception.
1
2
3
4
5

annee = input ()
try : # On essaye de convertir l ' ann e en entier
annee = int ( annee )
except :
print ( " Erreur lors de la conversion de l ' ann e . " )

Vous pouvez tester ce code en prcisant plusieurs valeurs diffrentes pour la variable
annee, comme 2010 ou annee2010 .
Dans le titre de cette section, jai parl de forme minimale et ce nest pas pour rien.
Dabord, il va de soi que vous ne pouvez intgrer cette solution directement dans votre
code. En effet, si lutilisateur saisit une anne impossible convertir, le systme affiche
certes une erreur mais finit par planter (puisque lanne, au final, na pas t convertie).
Une des solutions envisageables est dattribuer une valeur par dfaut lanne, en cas
derreur, ou de redemander lutilisateur de saisir lanne.
Ensuite et surtout, cette mthode est assez grossire. Elle essaye une instruction et
intercepte nimporte quelle exception lie cette instruction. Ici, cest acceptable car
nous navons pas normment derreurs possibles sur cette instruction. Mais cest une
mauvaise habitude prendre. Voici une manire plus lgante et moins dangereuse.
81

CHAPITRE 8. LES EXCEPTIONS

Forme plus complte


Nous allons apprendre complter notre bloc try. Comme je lai indiqu plus haut, la
forme minimale est viter pour plusieurs raisons.
Dabord, elle ne diffrencie pas les exceptions qui pourront tre leves dans le bloc try.
Ensuite, Python peut lever des exceptions qui ne signifient pas ncessairement quil y
a eu une erreur.

Excuter le bloc except pour un type dexception prcis


Dans lexemple que nous avons vu plus haut, on ne pense qu un type dexceptions
susceptible dtre lev : le type ValueError, qui trahirait une erreur de conversion.
Voyons un autre exemple :
1
2
3
4

try :

resultat = numerateur / denominateur


except :
print ( " Une erreur est survenue ... laquelle ? " )

Ici, plusieurs erreurs sont susceptibles dintervenir, chacune levant une exception diffrente.
NameError : lune des variables numerateur ou denominateur na pas t dfinie (elle
nexiste pas). Si vous essayez dans linterprteur linstruction print(numerateur)
alors que vous navez pas dfini la variable numerateur, vous aurez la mme erreur.
TypeError : lune des variables numerateur ou denominateur ne peut diviser ou tre
divise (les chanes de caractres ne peuvent tre divises, ni diviser dautres types,
par exemple). Cette exception est leve car vous utilisez loprateur de division /
sur des types qui ne savent pas quoi en faire.
ZeroDivisionError : encore elle ! Si denominateur vaut 0, cette exception sera
leve.
Cette numration nest pas une liste exhaustive de toutes les exceptions qui peuvent
tre leves lexcution de ce code. Elle est surtout l pour vous montrer que plusieurs
erreurs peuvent se produire sur une instruction (cest encore plus flagrant sur un bloc
constitu de plusieurs instructions) et que la forme minimale intercepte toutes ces
erreurs sans les distinguer, ce qui peut tre problmatique dans certains cas.
Tout se joue sur la ligne du except. Entre ce mot-cl et les deux points, vous pouvez
prciser le type de lexception que vous souhaitez traiter.
1
2
3
4

try :

resultat = numerateur / denominateur


except NameError :
print ( " La variable numerateur ou denominateur n 'a pas t d
finie . " )

Ce code ne traite que le cas o une exception NameError est leve. On peut intercepter
les autres types dexceptions en crant dautres blocs except la suite :
82

FORME PLUS COMPLTE


1
2
3
4
5
6
7
8

try :

resultat = numerateur / denominateur


except NameError :
print ( " La variable numerateur ou denominateur n 'a pas t d
finie . " )
except TypeError :
print ( " La variable numerateur ou denominateur poss de un
type incompatible avec la division . " )
except ZeroDivisionError :
print ( " La variable denominateur est gale 0 . " )

Cest mieux non ?


Allez un petit dernier !
On peut capturer lexception et afficher son message grce au mot-cl as que vous avez
dj vu dans un autre contexte (si si, rappelez-vous de limportation de modules).
1
2
3
4

try :

# Bloc de test
except t y pe _ d e_l_exception as exception_retournee :
print ( " Voici l ' erreur : " , exception_retournee )

Dans ce cas, une variable exception_retournee est cre par Python si une exception
du type prcis est leve dans le bloc try.
Je vous conseille de toujours prciser un type dexceptions aprs except (sans ncessairement capturer lexception dans une variable, bien entendu). Dabord, vous ne devez
pas utiliser try comme une mthode miracle pour tester nimporte quel bout de code.
Il est important que vous gardiez le maximum de contrle sur votre code. Cela signifie
que, si une erreur se produit, vous devez tre capable de lanticiper. En pratique, vous
nirez pas jusqu tester si une variable quelconque existe bel et bien, il faut faire un
minimum confiance son code. Mais si vous tes en face dune division et que le dnominateur pourrait avoir une valeur de 0, placez la division dans un bloc try et prcisez,
aprs le except, le type de lexception qui risque de se produire (ZeroDivisionError
dans cet exemple).
Si vous adoptez la forme minimale ( savoir except sans prciser un type dexception
qui pourrait se produire sur le bloc try), toutes les exceptions seront traites de la mme
faon. Et mme si exception = erreur la plupart du temps, ce nest pas toujours le
cas. Par exemple,Python lve
 une exception quand vous voulez fermer votre programme
avec le raccourci CTRL + C . Ici vous ne voyez peut-tre pas le problme mais si votre
bloc
 try est dans une boucle, vous ne pourrez pas arrter votre programme avec CTRL 
+ C , puisque lexception sera traite par votre except.
Je vous conseille donc de toujours prciser un type dexception possible aprs votre
except. Vous pouvez bien entendu faire des tests dans linterprteur de commandes
Python pour reproduire lexception que vous voulez traiter et ainsi connatre son type.
83

CHAPITRE 8. LES EXCEPTIONS

Les mots-cls else et finally


Ce sont deux mots-cls qui vont nous permettre de construire un bloc try plus complet.
Le mot-cl else
Vous avez dj vu ce mot-cl et jespre que vous vous en rappelez. Dans un bloc try,
else va permettre dexcuter une action si aucune erreur ne survient dans le bloc. Voici
un petit exemple :
1
2
3
4
5
6
7
8
9
10

try :

resultat = numerateur / denominateur


except NameError :
print ( " La variable numerateur ou denominateur n 'a pas t d
finie . " )
except TypeError :
print ( " La variable numerateur ou denominateur poss de un
type incompatible avec la division . " )
except ZeroDivisionError :
print ( " La variable denominateur est gale 0 . " )
else :
print ( " Le r sultat obtenu est " , resultat )

Dans les faits, on utilise assez peu else. La plupart des codeurs prfre mettre la ligne
contenant le print directement dans le bloc try. Pour ma part, je trouve que cest
important de distinguer entre le bloc try et ce qui seffectue ensuite. La ligne du print
ne produira vraisemblablement aucune erreur, inutile de la placer dans le bloc try.
Le mot-cl finally
finally permet dexcuter du code aprs un bloc try, quelle que soit le rsultat de
lexcution dudit bloc. La syntaxe est des plus simples :
1
2
3
4
5
6

try :

# Test d ' instruction ( s )


except TypeDInstruction :
# Traitement en cas d ' erreur
finally :
# Instruction ( s ) ex cut e ( s ) qu ' il y ait eu des erreurs ou
non

Est-ce que cela ne revient pas au mme si on met du code juste aprs le bloc ?

Pas tout fait. Le bloc finally est excut dans tous les cas de figures. Quand bien
mme Python trouverait une instruction return dans votre bloc except par exemple,
il excutera le bloc finally.
84

LES ASSERTIONS

Un petit bonus : le mot-cl pass


Il peut arriver, dans certains cas, que lon souhaite tester un bloc dinstructions. . . mais
ne rien faire en cas derreur. Toutefois, un bloc try ne peut tre seul.
1
2
3
4

>>> try :
...
1/0
...
File " < stdin >" , line 3

5
6
7

^
SyntaxError : invalid syntax

Il existe un mot-cl que lon peut utiliser dans ce cas. Son nom est pass et sa syntaxe
est trs simple dutilisation :
1
2
3
4

try :

# Test d ' instruction ( s )


except t y pe _ d e_l_exception : # Rien ne doit se passer en cas d '
erreur
pass

Je ne vous encourage pas particulirement utiliser ce mot-cl mais il existe, et vous


le savez prsent.
pass nest pas un mot-cl propre aux exceptions : on peut galement le trouver dans
des conditions ou dans des fonctions que lon souhaite laisser vides.
Voil, nous avons vu lessentiel. Il nous reste faire un petit point sur les assertions et
voir comment lever une exception (ce sera trs rapide).

Les assertions
Les assertions sont un moyen simple de sassurer, avant de continuer, quune condition
est respecte. En gnral, on les utilise dans des blocs try ... except.
Voyons comment cela fonctionne : nous allons pour loccasion dcouvrir un nouveau
mot-cl (encore un), assert. Sa syntaxe est la suivante :
1

assert test

Si le test renvoie True, lexcution se poursuit normalement. Sinon, une exception


AssertionError est leve.
Voyons un exemple :
1
2
3
4
5

>>> var = 5
>>> assert var == 5
>>> assert var == 8
Traceback ( most recent call last ) :
File " < stdin >" , line 1 , in < module >

85

CHAPITRE 8. LES EXCEPTIONS


6
7

AssertionError
>>>

Comme vous le voyez, la ligne 2 sexcute sans problme et ne lve aucune exception.
On teste en effet si var == 5. Cest le cas, le test est donc vrai, aucune exception nest
leve.
la ligne suivante, cependant, le test est var == 8. Cette fois, le test est faux et une
exception du type AssertionError est leve.

quoi cela sert-il, concrtement ?

Dans le programme testant si une anne est bissextile, on pourrait vouloir sassurer
que lutilisateur ne saisit pas une anne infrieure ou gale 0 par exemple. Avec les
assertions, cest trs facile faire :
1
2
3
4
5
6
7
8

annee = input ( " Saisissez une ann e sup rieure 0 : " )


try :
annee = int ( annee ) # Conversion de l ' ann e
assert annee > 0
except ValueError :
print ( " Vous n ' avez pas saisi un nombre . " )
except AssertionError :
print ( " L ' ann e saisie est inf rieure ou gale 0 . " )

Lever une exception


Hmmm. . . je vois dici les mines sceptiques (non non, ne vous cachez pas !). Vous vous
demandez probablement pourquoi vous feriez le boulot de Python en levant des exceptions. Aprs tout, votre travail, cest en thorie dviter que votre programme plante.
Parfois, cependant, il pourra tre utile de lever des exceptions. Vous verrez tout lintrt
du concept quand vous crerez vos propres classes. . . mais ce nest pas pour tout de
suite. En attendant, je vais vous donner la syntaxe et vous pourrez faire quelques tests,
vous verrez de toute faon quil ny a rien de compliqu.
On utilise un nouveau mot-cl pour lever une exception. . . le mot-cl raise.
1

raise TypeDeLException ( " message afficher " )

Prenons un petit exemple, toujours autour de notre programme bissextile. Nous


allons lever une exception de type ValueError si lutilisateur saisit une anne ngative
ou nulle.
1
2
3

86

annee = input () # L ' utilisateur saisit l ' ann e


try :
annee = int ( annee ) # On tente de convertir l ' ann e

LEVER UNE EXCEPTION


4
5
6
7

if annee <= 0 :
raise ValueError ( " l ' ann e saisie est n gative ou nulle "
)
except ValueError :
print ( " La valeur saisie est invalide ( l ' ann e est peut - tre
n gative ) . " )

Ce que nous venons de faire est ralisable sans lutilisation des exceptions mais ctait
surtout pour vous montrer la syntaxe dans un vritable contexte. Ici, on lve une
exception que lon intercepte immdiatement ou presque, lintrt est donc limit. Bien
entendu, la plupart du temps ce nest pas le cas.
Il reste des choses dcouvrir sur les exceptions, mais on en a assez fait pour ce
chapitre et cette partie. Je ne vous demande pas de connatre toutes les exceptions
que Python est amen utiliser (certaines dentre elles pourront dailleurs nexister
que dans certains modules). En revanche, vous devez tre capables de savoir, grce
linterprteur de commandes, quelles exceptions peuvent tre leves par Python dans
une situation donne.

En rsum
On peut intercepter les erreurs (ou exceptions) leves par notre code grce aux blocs
try except.
La syntaxe dune assertion est assert test:.
Les assertions lvent une exception AssertionError si le test choue.
On peut lever une exception grce au mot-cl raise suivi du type de lexception.

87

CHAPITRE 8. LES EXCEPTIONS

88

Chapitre

TP : tous au ZCasino
Difficult :
heure de vrit a sonn ! Cest dans ce premier TP que je vais faire montre de ma
cruaut sans limite en vous lchant dans la nature. . . ou presque. Ce nest pas tout
fait votre premier TP, dans le sens o le programme du chapitre 4, sur les conditions,
constituait votre premire exprience en la matire. Mais, ce moment-l, nous navions
pas fait un programme trs. . . rcratif.

Cette fois, nous allons nous atteler au dveloppement dun petit jeu de casino. Vous trouverez le dtail de lnonc plus bas, ainsi que quelques conseils pour la ralisation de ce
TP.
Si, durant ce TP, vous sentez que certaines connaissances vous manquent, revenez en
arrire ; prenez tout votre temps, on nest pas press !

89

CHAPITRE 9. TP : TOUS AU ZCASINO

Notre sujet
Dans ce chapitre, nous allons essayer de faire un petit programme que nous appellerons
ZCasino. Il sagira dun petit jeu de roulette trs simplifi dans lequel vous pourrez miser
une certaine somme et gagner ou perdre de largent (telle est la fortune, au casino !).
Quand vous navez plus dargent, vous avez perdu.

Notre rgle du jeu


Bon, la roulette, cest trs sympathique comme jeu, mais un peu trop compliqu pour
un premier TP. Alors, on va simplifier les rgles et je vous prsente tout de suite ce que
lon obtient :
Le joueur mise sur un numro compris entre 0 et 49 (50 numros en tout). En
choisissant son numro, il y dpose la somme quil souhaite miser.
La roulette est constitue de 50 cases allant naturellement de 0 49. Les numros
pairs sont de couleur noire, les numros impairs sont de couleur rouge. Le croupier
lance la roulette, lche la bille et quand la roulette sarrte, relve le numro de la
case dans laquelle la bille sest arrte. Dans notre programme, nous ne reprendrons
pas tous ces dtails matriels mais ces explications sont aussi lintention de
ceux qui ont eu la chance dviter les salles de casino jusquici. Le numro sur lequel
sest arrte la bille est, naturellement, le numro gagnant.
Si le numro gagnant est celui sur lequel le joueur a mis (probabilit de 1/50, plutt
faible), le croupier lui remet 3 fois la somme mise.
Sinon, le croupier regarde si le numro mis par le joueur est de la mme couleur que
le numro gagnant (sils sont tous les deux pairs ou tous les deux impairs). Si cest
le cas, le croupier lui remet 50 % de la somme mise. Si ce nest pas le cas, le joueur
perd sa mise.
Dans les deux scnarios gagnants vus ci-dessus (le numro mis et le numro gagnant
sont identiques ou ont la mme couleur), le croupier remet au joueur la somme initialement mise avant dy ajouter ses gains. Cela veut dire que, dans ces deux scnarios,
le joueur rcupre de largent. Il ny a que dans le troisime cas quil perd la somme
mise 1 .

Organisons notre projet


Pour ce projet, nous nallons pas crire de module. Nous allons utiliser ceux de Python, qui sont bien suffisants pour linstant, notamment celui permettant gnrer de
lalatoire, que je vais prsenter plus bas. En attendant, ne vous privez quand mme
pas de crer un rpertoire et dy mettre le fichier ZCasino.py, tout va se jouer ici.
Vous tes capables dcrire le programme ZCasino tel quexpliqu dans la premire
partie sans difficult. . . sauf pour gnrer des nombres alatoires. Python a ddi tout
1. On utilisera pour devise le dollar $ la place de leuro pour des raisons dencodage sous la
console Windows.

90

ORGANISONS NOTRE PROJET


un module la gnration dlments pseudo-alatoires, le module random.

Le module random
Dans ce module, nous allons nous intresser particulirement la fonction randrange
qui peut sutiliser de deux manires :
en ne prcisant quun paramtre (randrange(6) renvoie un nombre alatoire compris
entre 0 et 5) ;
en prcisant deux paramtres (randrange(1, 7) : renvoie un nombre alatoire compris entre 1 et 6, ce qui est utile, par exemple, pour reproduire une exprience avec
un d six faces).
Pour tirer un nombre alatoire compris entre 0 et 49 et simuler ainsi lexprience du
jeu de la roulette, nous allons donc utiliser linstruction randrange(50).
Il existe dautres faons dutiliser randrange mais nous nen aurons pas besoin ici et
je dirais mme que, pour ce programme, seule la premire utilisation vous sera utile.
Nhsitez pas faire des tests dans linterprteur de commandes (vous navez pas oubli
o cest, hein ?) et essayez plusieurs syntaxes de la fonction randrange. Je vous rappelle
quelle se trouve dans le module random, noubliez pas de limporter.

Arrondir un nombre
Vous lavez peut-tre bien not, dans lexplication des rgles je spcifiais que si le joueur
misait sur la bonne couleur, il obtenait 50% de sa mise. Oui mais. . . cest quand mme
mieux de travailler avec des entiers. Si le joueur mise 3$, par exemple, on lui rend 1,5$.
Cest encore acceptable mais, si cela se poursuit, on risque darriver des nombres
flottants avec beaucoup de chiffres aprs la virgule. Alors autant arrondir au nombre
suprieur. Ainsi, si le joueur mise 3$, on lui rend 2$. Pour cela, on va utiliser une
fonction du module math nomme ceil. Je vous laisse regarder ce quelle fait, il ny a
rien de compliqu.

vous de jouer
Voil, vous avez toutes les cls en main pour coder ce programme. Prenez le temps
quil faut pour y arriver, ne vous ruez pas sur la correction, le but du TP est que vous
appreniez coder vous-mmes un programme. . . et celui-ci nest pas trs difficile. Si
vous avez du mal, morcelez le programme, ne codez pas tout dun coup. Et nhsitez
pas passer par linterprteur pour tester des fonctionnalits : cest rellement une
chance qui vous est donne, ne la laissez pas passer.
vous de jouer !
91

CHAPITRE 9. TP : TOUS AU ZCASINO

Correction !
Cest encore une fois lheure de comparer nos versions. Et, une fois encore, il est trs
peu probable que vous ayez un code identique au mien. Donc si le vtre fonctionne,
je dirais que cest lessentiel. Si vous vous heurtez des difficults insurmontables, la
correction est l pour vous aider.

. . . ATTENTION. . . voici. . . la solution !

# Ce fichier abrite le code du ZCasino , un jeu de roulette


adapt

2
3
4
5

import os
from random import randrange
from math import ceil

6
7
8
9
10

# D claration des variables de d part


argent = 1000 # On a 1000 $ au d but du jeu
continuer_partie = True # Bool en qui est vrai tant qu ' on doit
# continuer la partie

11
12

print ( " Vous vous installez la table de roulette avec " , argent
, "$.")

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

while continuer_partie : # Tant qu ' on doit continuer la partie


# on demande l ' utilisateur de saisir le nombre sur
# lequel il va miser
nombre_mise = -1
while nombre_mise < 0 or nombre_mise > 49 :
nombre_mise = input ( " Tapez le nombre sur lequel vous
voulez miser ( entre 0 et 49 ) : " )
# On convertit le nombre mis
try :
nombre_mise = int ( nombre_mise )
except ValueError :
print ( " Vous n ' avez pas saisi de nombre " )
nombre_mise = -1
continue
if nombre_mise < 0 :
print ( " Ce nombre est n gatif " )
if nombre_mise > 49 :
print ( " Ce nombre est sup rieur 49 " )

31
32
33
34
35

92

# pr sent , on s lectionne la somme miser sur le nombre


mise = 0
while mise <= 0 or mise > argent :
mise = input ( " Tapez le montant de votre mise : " )

CORRECTION !
36
37
38
39
40
41
42
43
44
45
46

# On convertit la mise
try :
mise = int ( mise )
except ValueError :
print ( " Vous n ' avez pas saisi de nombre " )
mise = -1
continue
if mise <= 0 :
print ( " La mise saisie est n gative ou nulle . " )
if mise > argent :
print ( " Vous ne pouvez miser autant , vous n ' avez que
" , argent , " $ " )

47
48
49
50
51

# Le nombre mis et la mise ont t s lectionn s par


# l ' utilisateur , on fait tourner la roulette
numero_gagnant = randrange ( 50 )
print ( " La roulette tourne ... ... et s ' arr te sur le num ro "
, numero_gagnant )

52
53
54
55
56
57
58
59
60
61
62
63

# On tablit le gain du joueur


if numero_gagnant == nombre_mise :
print ( " F licitations ! Vous obtenez " , mise * 3 , " $ ! " )
argent += mise * 3
elif numero_gagnant % 2 == nombre_mise % 2 : # ils sont de
la m me couleur
mise = ceil ( mise * 0 . 5 )
print ( " Vous avez mis sur la bonne couleur . Vous
obtenez " , mise , " $ " )
argent += mise
else :
print ( " D sol l 'ami , c ' est pas pour cette fois . Vous
perdez votre mise . " )
argent -= mise

64
65
66
67
68
69
70
71
72
73
74
75

# On interrompt la partie si le joueur est ruin


if argent <= 0 :
print ( " Vous tes ruin ! C ' est la fin de la partie . " )
continuer_partie = False
else :
# On affiche l ' argent du joueur
print ( " Vous avez pr sent " , argent , " $ " )
quitter = input ( " Souhaitez - vous quitter le casino ( o / n )
? ")
if quitter == " o " or quitter == " O " :
print ( " Vous quittez le casino avec vos gains . " )
continuer_partie = False

76
77
78

# On met en pause le syst me ( Windows )


os . system ( " pause " )

93

CHAPITRE 9. TP : TOUS AU ZCASINO


Pour accder en ligne au code source de la solution, utilisez le code web suivant :


Copier ce code
B
.
Code web : 366476


Encore une fois, noubliez pas la ligne spcifiant lencodage si vous voulez viter les
surprises.
Une petite chose qui pourrait vous surprendre est la construction des boucles pour
tester si le joueur a saisi une valeur correcte (quand on demande lutilisateur de
taper un nombre entre 0 et 49 par exemple, il faut sassurer quil la bien fait). Cest
assez simple en vrit : on attend que le joueur saisisse un nombre. Si le nombre nest
pas valide, on demande nouveau au joueur de saisir ce nombre. Jen ai profit pour
utiliser le concept des exceptions afin de vrifier que lutilisateur saisit bien un nombre.
Comme vous lavez vu, si ce nest pas le cas, on affiche un message derreur. La valeur
de la variable qui contient le nombre est remise -1 (cest--dire une valeur qui indique
la boucle que nous navons toujours pas obtenu de lutilisateur une valeur valides) et
on utilise le mot-cl continue pour passer les autres instructions du bloc (sans quoi
vous verriez safficher un autre message indiquant que le nombre saisi est ngatif. . . cest
plus pratique ainsi). De cette faon, si lutilisateur fournit une donne inconvertible, le
jeu ne plante pas et lui redemande tout simplement de taper une valeur valide.
La boucle principale fonctionne autour dun boolen. On utilise une variable nomme
continuer_partie qui vaut vrai tant quon doit continuer la partie. Une fois que
la partie doit sinterrompre, elle passe faux . Notre boucle globale, qui gre le
droulement de la partie, travaille sur ce boolen ; par consquent, ds quil passe la
valeur faux , la boucle sinterrompt et le programme se met en pause. Tout le reste,
vous devriez le comprendre sans aide, les commentaires sont l pour vous expliquer. Si
vous avez des doutes, vous pouvez tester les lignes dinstructions problmatiques dans
votre interprteur de commandes Python : encore une fois, noubliez pas cet outil.

Et maintenant ?
Prenez bien le temps de lire ma version et surtout de modifier la vtre, si vous tes
arrivs une version qui fonctionne bien ou qui fonctionne presque. Ne mettez pas ce
projet la corbeille sous prtexte que nous avons fini de le coder et quil marche. On
peut toujours amliorer un projet et celui-ci ne fait videmment pas exception. Vous
trouverez probablement de nouveaux concepts, dans la suite de ce livre, qui pourront
tre utiliss dans le programme de ZCasino.

94

Deuxime partie

La Programmation Oriente
Objet ct utilisateur

95

Chapitre

10

Notre premier objet : les chanes de


caractres
Difficult :

es objets. . . vaste sujet ! Avant den crer, nous allons dabord voir de quoi il sagit.
Nous allons commencer avec les chanes de caractres, un type que vous pensez bien
connatre.

Dans ce chapitre, vous allez dcouvrir petit petit le mcanisme qui se cache derrire la
notion dobjet. Ces derniers font partie des notions incontournables en Python, tant donn
que tout ce que nous avons utilis jusquici. . . est un objet !

97

CHAPITRE 10. NOTRE PREMIER OBJET : LES CHANES DE CARACTRES

Vous avez dit objet ?


La premire question qui risque de vous empcher de dormir si je ny rponds pas tout
de suite, cest :
Mais cest quoi un objet ?

Eh bien, jai lu beaucoup de dfinitions trs diffrentes et je nai pas trouv de point
commun toutes ces dfinitions. Nous allons donc partir dune dfinition incomplte
mais qui suffira pour linstant : un objet est une structure de donnes, comme
les variables, qui peut contenir elle-mme dautres variables et fonctions.
On toffera plus loin cette dfinition, elle suffit bien pour le moment.
Je ne comprends rien. Passe encore quune variable en contienne dautres,
aprs tout les chanes de caractres contiennent bien des caractres, mais
quune variable contienne des fonctions. . . Cela rime quoi ?
Je pourrais passer des heures expliquer la thorie du concept que vous nen seriez pas
beaucoup plus avancs. Jai choisi de vous montrer les objets par lexemple et donc,
vous allez trs rapidement voir ce que tout cela signifie. Mais vous allez devoir me faire
confiance, au dbut, sur lutilit de la mthode objet.
Avant dattaquer, une petite prcision. Jai dit quun objet tait un peu comme une
variable. . . en fait, pour tre exact, il faut dire quune variable est un objet. Toutes
les variables avec lesquelles nous avons travaill jusquici sont des objets. Les fonctions
que nous avons vues sont galement des objets. En Python, tout est objet : gardez cela
lesprit.

Les mthodes de la classe str


Oh la la, jen vois qui grimacent rien quen lisant le titre. Vous navez pourtant aucune
raison de vous inquiter ! On va y aller tout doucement.
Posons un problme : comment peut-on passer une chane de caractres en minuscules ?
Si vous navez lu jusqu prsent que les premiers chapitres, vous ne pourrez pas faire cet
exercice ; jai volontairement vit de trop aborder les chanes de caractres jusquici.
Mais admettons que vous arriviez coder une fonction prenant en paramtre la chane
en question. Vous aurez un code qui ressemble ceci :
1
2
3

>>> chaine = " NE CRIE PAS SI FORT !"


>>> me t tr e_en_minuscule ( chaine )
ne crie pas si fort !

Sachez que, dans les anciennes versions de Python, il y avait un module spcialis dans
98

LES MTHODES DE LA CLASSE STR


le traitement des chanes de caractres. On importait ce module et on pouvait appeler
la fonction passant une chane en minuscules. Ce module existe dailleurs encore et
reste utilis pour certains traitements spcifiques. Mais on va dcouvrir ici une autre
faon de faire. Regardez attentivement :
1
2
3

>>> chaine = " NE CRIE PAS SI FORT !"


>>> chaine . lower () # Mettre la cha ne en minuscule
ne crie pas si fort !

La fonction lower est une nouveaut pour vous. Vous devez reconnatre le point .
qui symbolisait dj, dans le chapitre sur les modules, une relation dappartenance (a.b
signifiait que b tait contenu dans a). Ici, il possde la mme signification : la fonction
lower est une fonction de la variable chaine.
La fonction lower est propre aux chanes de caractres. Toutes les chanes peuvent
y faire appel. Si vous tapez type(chaine) dans linterprteur, vous obtenez <class
str>. Nous avons dit quune variable est issue dun type de donne. Je vais prsent
reformuler : un objet est issu dune classe. La classe est une forme de type de donne,
sauf quelle permet de dfinir des fonctions et variables propres au type. Cest pour cela
que, dans toutes les chanes de caractres, on peut appeler la fonction lower. Cest tout
simplement parce que la fonction lower a t dfinie dans la classe str. Les fonctions
dfinies dans une classe sont appeles des mthodes.
Rcapitulons. Nous avons dcouvert :
Les objets, que jai prsents comme des variables, pouvant contenir dautres variables ou fonctions (que lon appelle mthodes). On appelle une mthode dun
objet grce objet.methode().
Les classes, que jai prsentes comme des types de donnes. Une classe est un
modle qui servira construire un objet ; cest dans la classe quon va dfinir les
mthodes propres lobjet.
Voici le mcanisme qui vous permet dappeler la mthode lower dune chane :
1. Les dveloppeurs de Python ont cr la classe str qui est utilise pour crer des
chanes de caractres. Dans cette classe, ils ont dfini plusieurs mthodes, comme
lower, qui pourront tre utilises par nimporte quel objet construit sur cette
classe.
2. Quand vous crivez chaine = "NE CRIE PAS SI FORT !", Python reconnat quil
doit crer une chane de caractres. Il va donc crer un objet daprs la classe (le
modle) qui a t dfinie ltape prcdente.
3. Vous pouvez ensuite appeler toutes les mthodes de la classe str depuis lobjet
chaine que vous venez de crer.
Ouf ! Cela fait beaucoup de choses nouvelles, du vocabulaire et des concepts un peu
particuliers.
Vous ne voyez peut-tre pas encore tout lintrt davoir des mthodes dfinies dans
une certaine classe. Cela permet dabord de bien sparer les diverses fonctionnalits
99

CHAPITRE 10. NOTRE PREMIER OBJET : LES CHANES DE CARACTRES


(on ne peut pas passer en minuscules un nombre entier, cela na aucun sens). Ensuite,
cest plus intuitif, une fois pass le choc de la premire rencontre.
Bon, on parle, on parle, mais on ne code pas beaucoup !

Mettre en forme une chane


Non, vous nallez pas apprendre mettre une chane en gras, soulign, avec une police
Verdana de 15px. . . Nous ne sommes encore que dans une console. Nous venons de prsenter lower, il existe dautres mthodes. Avant tout, voyons un contexte dutilisation.
Certains dentre vous se demandent peut-tre lintrt de passer des chanes en minuscules. . . alors voici un petit exemple.
1
2

chaine = str () # Cr e une cha ne vide


# On aurait obtenu le m me r sultat en tapant chaine = ""

while chaine . lower () != " q " :


print ( " Tapez 'Q ' pour quitter ... " )
chaine = input ()

4
5
6
7

print ( " Merci ! " )

Vous devez comprendre rapidement ce programme. Dans une boucle, on demande


lutilisateur de taper la lettre q pour quitter. Tant que lutilisateur saisit une autre

lettre, la boucle continue de sexcuter. Ds que lutilisateur appuie sur la touche Q 
de son clavier, la boucle sarrte et le programme affiche Merci ! . Cela devrait vous
rappeler quelque chose. . . direction le TP de la partie 1 pour ceux qui ont la mmoire
courte.
La petite nouveaut rside dans le test de la boucle : chaine.lower() != "q". On
prend la chane saisie par lutilisateur, on la passe en minuscules et on regarde si elle
est diffrente de q . Cela veut dire que lutilisateur peut taper q en majuscule
ou en minuscule, dans les deux cas la boucle sarrtera.
Notez que chaine.lower() renvoie la chane en minuscules mais ne modifie pas la
chane. Cest trs important, nous verrons pourquoi dans le prochain chapitre.
Notez aussi que nous avons appel la fonction str pour crer une chane vide. Je ne
vais pas trop compliquer les choses mais sachez quappeler ainsi un type en tant que
fonction permet de crer un objet de la classe. Ici, str() cre un objet chane de
caractres. Nous avons vu dans la premire partie le mot-cl int(), qui cre aussi un
entier 1 .
Bon, voyons dautres mthodes. Je vous invite tester mes exemples (ils sont comments, mais on retient mieux en essayant par soi-mme).
1
2
3

>>> minuscules = " une chaine en minuscules "


>>> minuscules . upper () # Mettre en majuscules
UNE CHAINE EN MINUSCULES
1. Si ncessaire depuis un autre type, ce qui permet de convertir une chane en entier.

100

LES MTHODES DE LA CLASSE STR


4
5
6
7
8
9
10
11
12

>>> minuscule . capitalize () # La premi re lettre en majuscule


Une chaine en minuscules
>>> espaces = "
une chaine avec des espaces
"
>>> espaces . strip () # On retire les espaces au d but et la
fin de la cha ne
une chaine avec des espaces
>>> titre = " introduction "
>>> titre . upper () . center (20)

INTRODUCTION

>>>

La dernire instruction mrite quelques explications.


On appelle dabord la mthode upper de lobjet titre. Cette mthode, comme vous
lavez vu plus haut, renvoie en majuscules la chane de caractres contenue dans lobjet.
On appelle ensuite la mthode center, mthode que nous navons pas encore vue et
qui permet de centrer une chane. On lui passe en paramtre la taille de la chane
que lon souhaite obtenir. La mthode va ajouter alternativement un espace au dbut
et la fin de la chane, jusqu obtenir la longueur demande. Dans cet exemple,
titre contient la chane introduction, chane qui (en minuscules ou en majuscules)
mesure 12 caractres. On demande center de centrer cette chane dans un espace de
20 caractres. La mthode center va donc placer 4 espaces avant le titre et 4 espaces
aprs, pour faire 20 caractres en tout.
Bon, mais maintenant, sur quel objet travaille center ? Sur titre ? Non. Sur la chane
renvoye par titre.upper(), cest--dire le titre en majuscules. Cest pourquoi on peut
chaner ces deux mthodes : upper, comme la plupart des mthodes de chanes,
travaille sur une chane et renvoie une chane. . . qui elle aussi va possder les mthodes
propres une chane de caractres. Si ce nest pas trs clair, faites quelques tests,
avec titre.upper() et titre.center(20), en passant par une seconde variable si
ncessaire, pour vous rendre compte du mcanisme ; ce nest pas bien compliqu.
Je nai mis ici que quelques mthodes, il y en a bien dautres. Vous pouvez en voir la
liste dans laide, en tapant, dans linterprteur : help(str).

Formater et afficher une chane


Attends, on a appris faire cela depuis cinq bons chapitres ! On ne va pas
tout rapprendre quand mme ?
Heureusement que non ! Mais nous allons apprendre considrer ce que nous savons
travers le modle objet. Et vous allez vous rendre compte que, la plupart du temps,
nous navons fait queffleurer les fonctionnalits du langage.
Je ne vais pas revenir sur ce que jai dit, pour afficher une chane, on passe par la
fonction print.
1

chaine = " Bonjour tout le monde ! "

101

CHAPITRE 10. NOTRE PREMIER OBJET : LES CHANES DE CARACTRES


print ( chaine )

Rien de nouveau ici. En revanche, nous allons un peu changer nos habitudes en ce qui
concerne laffichage de plusieurs variables.
Jusquici, nous avons utilis print en lui imputant plusieurs paramtres. Cela fonctionne mais nous allons voir une mthode lgrement plus souple, qui dailleurs nest
pas seulement utile pour laffichage.
1
2
3
4
5

>>>
>>>
>>>
>>>

prenom = " Paul "


nom = " Dupont "
age = 21
print (" Je m appelle {0} {1} et j ai {2} ans .". format ( prenom
, nom , age ) )
Je m appelle Paul Dupont et j ai 21 ans .

Mais ! Cest quoi cela ?

Question lgitime. Voyons un peu.


Premire syntaxe de la mthode format
Nous avons utilis une mthode de la classe str pour formater notre chane. De gauche
droite, nous avons :
une chane de caractres qui ne prsente rien de particulier, sauf ces accolades entourant des nombres, dabord 0, puis 1, puis 2 ;
nous appelons la mthode format de cette chane en lui passant en paramtres les
variables afficher, dans un ordre bien prcis ;
quand Python excute cette mthode, il remplace dans notre chane {0} par la
premire variable passe la mthode format (soit le prnom), {1} par la deuxime
variable. . . et ainsi de suite.
Souvenez-vous quen programmation, on commence compter partir de 0.

Bien, mais on aurait pu faire exactement la mme chose en passant plusieurs


valeurs print, non ?
Absolument. Mais rappelez-vous que cette fonctionnalit est bien plus puissante quun
simple affichage, vous pouvez formater des chanes de cette faon. Ici, nous avons
directement affich la chane formate, mais nous aurions pu la stocker :
102

LES MTHODES DE LA CLASSE STR

1
2

>>> nouvelle_chaine = " Je m appelle {0} {1} et j ai {2} ans .".


format ( prenom , nom , age )
>>>

Pour faire la mme chose sans utiliser format, on aurait d concatner des chanes,
cest--dire les mettre bout bout en respectant une certaine syntaxe. Nous allons voir
cela un peu plus loin mais cette solution reste plus lgante.
Dans cet exemple, nous avons appel les variables dans lordre o nous les placions
dans format, mais ce nest pas une obligation. Considrez cet exemple :
1
2
3
4
5
6
7

>>>
>>>
>>>
>>>
...

prenom = " Paul "


nom = " Dupont "
age = 21
print ( \
" Je m appelle {0} {1} ({3} {0} pour l administration ) et
j ai {2} " \
...
" ans .". format ( prenom , nom , age , nom . upper () ) )
Je m appelle Paul Dupont ( DUPONT Paul pour l administration ) et
j ai 21 ans .

Jai coup notre instruction, plutt longue, laide du signe \ plac avant un saut
de ligne, pour indiquer Python que linstruction se prolongeait au-dessous.
Si vous avez du mal comprendre lexemple, relisez linstruction en remplaant vousmmes les nombres entre accolades par les variables.
Dans la plupart des cas, on ne prcise pas le numro de la variable entre
accolades.

1
2
3
4
5

>>> date = " Dimanche 24 juillet 2011"


>>> heure = "17:00"
>>> print (" Cela s est produit le {} , {}.". format ( date , heure )
)
Cela s est produit le Dimanche 24 juillet 2011 , 17:00.
>>>

Naturellement, cela ne fonctionne que si vous donnez les variables dans le bon ordre
dans format.
Cette syntaxe suffit la plupart du temps mais elle nest pas forcment intuitive quand
on insre beaucoup de variables : on doit retenir leur position dans lappel format
pour comprendre laquelle est affiche tel endroit. Mais il existe une autre syntaxe.
103

CHAPITRE 10. NOTRE PREMIER OBJET : LES CHANES DE CARACTRES


Seconde syntaxe de la mthode format
On peut galement nommer les variables que lon va afficher, cest souvent plus intuitif
que dutiliser leur indice. Voici un nouvel exemple :
1
2
3
4
5
6

# formatage d ' une adresse


adresse = """
{ no_rue } , { nom_rue }
{ code_postal } { nom_ville } ( { pays } ) """
. format ( no_rue =5 , nom_rue = " rue des Postes " , code_postal = 75003
, nom_ville = " Paris " , pays = " France " )
print ( adresse )

. . . affichera :
1
2

5 , rue des Postes


75003 Paris ( France )

Je pense que vous voyez assez prcisment en quoi consiste cette deuxime syntaxe
de format. Au lieu de donner des nombres entre accolades, on spcifie des noms de
variables qui doivent correspondre ceux fournis comme mots-cls dans la mthode
format. Je ne mattarderai pas davantage sur ce point, je pense quil est assez clair
comme cela.
La concatnation de chanes
Nous allons glisser trs rapidement sur le concept de concatnation, assez intuitif
dailleurs. On cherche regrouper deux chanes en une, en mettant la seconde la
suite de la premire. Cela se fait le plus simplement du monde :
1
2
3
4
5
6
7
8
9
10
11

>>> prenom = " Paul "


>>> message = " Bonjour "
>>> chaine_complete = message + prenom # On utilise le symbole
+ pour concat ner deux cha nes
... print ( chaine_complete ) # R sultat :
BonjourPaul
>>> # Pas encore parfait , il manque un espace
... # Qu cela ne tienne !
... chaine_complete = message + " " + prenom
>>> print ( chaine_complete ) # R sultat :
Bonjour Paul
>>>

Cest assez clair je pense. Le signe + utilis pour ajouter des nombres est ici utilis
pour concatner deux chanes. Essayons prsent de concatner des chanes et des
nombres :
1
2

104

>>> age = 21
>>> message = "J ai " + age + " ans ."

PARCOURS ET SLECTION DE CHANES


3
4
5
6

Traceback ( most recent call last ) :


File " < stdin >" , line 1 , in < module >
TypeError : Can t convert int object to str implicitly
>>>

Python se fche tout rouge ! Certains langages auraient accept cette syntaxe sans
sourciller mais Python naime pas cela du tout.
Au dbut de la premire partie, nous avons dit que Python tait un langage typage
dynamique, ce qui signifie quil identifie lui-mme les types de donnes et que les
variables peuvent changer de type au cours du programme. Mais Python est aussi un
langage fortement typ, et cela veut dire que les types de donnes ne sont pas l
juste pour faire joli, on ne peut pas les ignorer. Ainsi, on veut ici ajouter une chane
un entier et une autre chane. Python ne comprend pas : est-ce que les chanes
contiennent des nombres quil doit convertir pour les ajouter lentier ou est-ce que
lentier doit tre converti en chane puis concatn avec les autres chanes ? Python ne
sait pas. Il ne le fera pas tout seul. Mais il se rvle tre de bonne volont puisquil suffit
de lui demander de convertir lentier pour pouvoir le concatner aux autres chanes.
1
2
3
4
5

>>> age = 21
>>> message = "J ai " + str ( age ) + " ans ."
>>> print ( message )
J ai 21 ans .
>>>

On appelle str pour convertir un objet en une chane de caractres, comme nous
avons appel int pour convertir un objet en entier. Cest le mme mcanisme, sauf
que convertir un entier en chane de caractres ne lvera vraissemblablement aucune
exception.
Le typage fort de Python est important, il est un fondement de sa philosophie. Jai
tendance considrer quun langage faiblement typ cre des erreurs qui sont plus
difficiles reprer alors quici, il nous suffit de convertir explicitement le type pour que
Python sache ce quil doit faire.

Parcours et slection de chanes


Nous avons vu trs rapidement dans la premire partie un moyen de parcourir des
chanes. Nous allons en voir ici un second qui fonctionne par indice.

Parcours par indice


Vous devez vous en souvenir : jai dit quune chane de caractres tait une squence
constitue. . . de caractres. En fait, une chane de caractres est elle-mme constitue
de chanes de caractres, chacune delles ntant compose que dun seul caractre.
105

CHAPITRE 10. NOTRE PREMIER OBJET : LES CHANES DE CARACTRES


Accder aux caractres dune chane
Nous allons apprendre accder aux lettres constituant une chane. Par exemple, nous
souhaitons slectionner la premire lettre dune chane.
1
2
3
4
5
6
7
8

>>>
>>>
S
>>>
l
>>>
!
>>>

chaine = " Salut les ZER0S !"


chaine [0] # Premi re lettre de la cha ne
chaine [2] # Troisi me lettre de la cha ne
chaine [ -1] # Derni re lettre de la cha ne

On prcise entre crochets [] lindice (la position du caractre auquel on souhaite accder).
Rappelez-vous, on commence compter partir de 0. La premire lettre est donc
lindice 0, la deuxime lindice 1, la troisime lindice 2. . . On peut accder aux
lettres en partant de la fin laide dun indice ngatif. Quand vous tapez chaine[-1],
vous accdez ainsi la dernire lettre de la chane (enfin, au dernier caractre, qui nest
pas une lettre ici).
On peut obtenir la longueur de la chane (le nombre de caractres quelle contient)
grce la fonction len.
1
2
3
4

>>> chaine = " Salut "


>>> len ( chaine )
5
>>>

Pourquoi ne pas avoir dfini cette fonction comme une mthode de la classe
str ? Pourquoi ne pourrait-on pas faire chaine.len() ?
En fait cest un peu le cas, mais nous le verrons bien plus loin. str nest quun exemple
parmi dautres de squences (on en dcouvrira dautres dans les prochains chapitres)
et donc les dveloppeurs de Python ont prfr crer une fonction qui travaillerait sur
les squences au sens large, plutt quune mthode pour chacune de ces classes.
Mthode de parcours par while
Vous en savez assez pour parcourir une chane grce la boucle while. Notez que, dans
la plupart des cas, on prfrera parcourir une squence avec for. Il est nanmoins bon
de savoir procder de diffrentes manires, cela vous sera utile parfois.
Voici le code auquel vous pourriez arriver :
1

106

chaine = " Salut "

PARCOURS ET SLECTION DE CHANES


2
3
4
5

i = 0 # On appelle l ' indice 'i ' par convention


while i < len ( chaine ) :
print ( chaine [ i ]) # On affiche le caract re chaque tour de
boucle
i += 1

Noubliez pas dincrmenter i, sinon vous allez avoir quelques surprises.


Si vous essayez daccder un indice qui nexiste pas (par exemple 25 alors que votre
chane ne fait que 20 caractres de longueur), Python lvera une exception de type
IndexError.
Enfin, une dernire petite chose : vous ne pouvez changer les lettres de la chane en
utilisant les indices.
1
2
3
4
5
6

>>> mot = " lac "


>>> mot [0] = " b " # On veut remplacer l par b
Traceback ( most recent call last ) :
File " < stdin >" , line 1 , in < module >
TypeError : str object does not support item assignment
>>>

Python nest pas content. Il ne veut pas que vous utilisiez les indices pour modifier des
caractres de la chane. Pour ce faire, il va falloir utiliser la slection.

Slection de chanes
Nous allons voir comment slectionner une partie de la chane. Si je souhaite, par
exemple, slectionner les deux premires lettres de la chane, je procderai comme dans
lexemple ci-dessous.
1
2
3
4
5
6

>>> presentation = " salut "


>>> presentation [0:2] # On s lectionne les deux premi res
lettres
sa
>>> presentation [2: len ( presentation ) ] # On s lectionne la cha
ne sauf les deux premi res lettres
lut
>>>

La slection consiste donc extraire une partie de la chane. Cette opration renvoie
le morceau de la chane slectionn, sans modifier la chane dorigine.
Sachez que lon peut slectionner du dbut de la chane jusqu un indice, ou dun
indice jusqu la fin de la chane, sans prciser autant dinformations que dans nos
exemples. Python comprend trs bien si on sous-entend certaines informations.
1
2

>>> presentation [:2] # Du d but jusqu la troisi me lettre non


comprise
sa

107

CHAPITRE 10. NOTRE PREMIER OBJET : LES CHANES DE CARACTRES


3
4
5

>>> presentation [2:] # De la troisi me lettre ( comprise ) la


fin
lut
>>>

Maintenant, nous pouvons reprendre notre exemple de tout lheure pour constituer
une nouvelle chane, en remplaant une lettre par une autre :
1
2
3
4
5

>>> mot = " lac "


>>> mot = " b " + mot [1:]
>>> print ( mot )
bac
>>>

Voil !
Cela reste assez peu intuitif, non ?

Pour remplacer des lettres, cela parat un peu lourd en effet. Et dailleurs on sen sert
assez rarement pour cela. Pour rechercher/remplacer, nous avons notre disposition les
mthodes count, find et replace, savoir compter , rechercher et remplacer .

En rsum
Les variables utilises jusquici sont en ralit des objets.
Les types de donnes utiliss jusquici sont en fait des classes. Chaque objet est
model sur une classe.
Chaque classe dfinit certaines fonctions, appeles mthodes, qui seront accessibles
depuis lobjet grce objet.methode(arguments).
On peut directement accder un caractre dune chane grce au code suivant :
chaine[position_dans_la_chaine].
Il est tout fait possible de slectionner une partie de la chane grce au code suivant :
chaine[indice_debut:indice_fin].

108

Chapitre

11

Les listes et tuples (1/2)


Difficult :
aurai russi vous faire connatre et, jespre, aimer le langage Python sans vous
apprendre les listes. Mais allons ! Cette poque est rvolue. Maintenant que nous commenons tudier lobjet sous toutes ses formes, je ne vais pas pouvoir garder le secret
plus longtemps : il existe des listes en Python. Pour ceux qui ne voient mme pas de quoi
je parle, vous allez vite vous rendre compte quavec les dictionnaires (que nous verrons plus
loin), cest un type, ou plutt une classe, dont on aura du mal se passer.

Les listes sont des squences. En fait, leur nom est plutt explicite, puisque ce sont des
objets capables de contenir dautres objets de nimporte quel type. On peut avoir une liste
contenant plusieurs nombres entiers (1, 2, 50, 2000 ou plus, peu importe), une liste contenant des flottants, une liste contenant des chanes de caractres... et une liste mlangeant
ces objets de diffrents types.

109

CHAPITRE 11. LES LISTES ET TUPLES (1/2)

Crons et ditons nos premires listes


Dabord cest quoi, une liste ?
En Python, les listes sont des objets qui peuvent en contenir dautres. Ce sont donc des
squences, comme les chanes de caractres, mais au lieu de contenir des caractres,
elles peuvent contenir nimporte quel objet. Comme dhabitude, on va soccuper du
concept des listes avant de voir tout son intrt.

Cration de listes
On a deux moyens de crer des listes. Si je vous dis que la classe dune liste sappelle,
assez logiquement, list, vous devriez dj voir une manire de crer une liste.
Non ? . . .
Vous allez vous habituer cette syntaxe :
1
2
3
4
5
6

>>> ma_liste = list () # On cr e une liste vide


>>> type ( ma_liste )
< class list >
>>> ma_liste
[]
>>>

L encore, on utilise le nom de la classe comme une fonction pour instancier un objet
de cette classe.
Quand vous affichez la liste, vous pouvez constater quelle est vide. Entre les crochets
(qui sont les dlimiteurs des listes en Python), il ny a rien. On peut galement utiliser
ces crochets pour crer une liste.
>>> ma_liste = [] # On cr e une liste vide
>>>

1
2

Cela revient au mme, vous pouvez vrifier. Toutefois, on peut galement crer une liste
non vide, en lui indiquant directement la cration les objets quelle doit contenir.
1
2
3
4

>>> ma_liste = [1 , 2 , 3 , 4 , 5] # Une liste avec cinq objets


>>> print ( ma_liste )
[1 , 2 , 3 , 4 , 5]
>>>

La liste que nous venons de crer compte cinq objets de type int. Ils sont classs par
ordre croissant. Mais rien de tout cela nest obligatoire.
Vous pouvez faire des listes de toute longueur.
Les listes peuvent contenir nimporte quel type dobjet.
110

CRONS ET DITONS NOS PREMIRES LISTES


Les objets dans une liste peuvent tre mis dans un ordre quelconque. Toutefois, la
structure dune liste fait que chaque objet a sa place et que lordre compte.
1
2

>>> ma_liste = [1 , 3.5 , " une chaine " , []]


>>>

Nous avons cr ici une liste contenant quatre objets de types diffrents : un entier, un
flottant, une chane de caractres et. . . une autre liste.
Voyons prsent comment accder aux lments dune liste :
1
2
3
4
5
6
7
8
9

>>> ma_liste = [ c , f , m ]
>>> ma_liste [0] # On acc de au premier l ment de la liste
c
>>> ma_liste [2] # Troisi me l ment
m
>>> ma_liste [1] = Z # On remplace f par Z
>>> ma_liste
[ c , Z , m ]
>>>

Comme vous pouvez le voir, on accde aux lments dune liste de la mme faon quon
accde aux caractres dune chane de caractres : on indique entre crochets lindice de
llment qui nous intresse.
Contrairement la classe str, la classe list vous permet de remplacer un lment par
un autre. Les listes sont en effet des types dits mutables.

Insrer des objets dans une liste


On dispose de plusieurs mthodes, dfinies dans la classe list, pour ajouter des lments dans une liste.
Ajouter un lment la fin de la liste
On utilise la mthode append pour ajouter un lment la fin dune liste.
1
2
3
4
5

>>>
>>>
>>>
[1 ,
>>>

ma_liste = [1 , 2 , 3]
ma_liste . append (56) # On ajoute 56 la fin de la liste
ma_liste
2 , 3 , 56]

Cest assez simple non ? On passe en paramtre de la mthode append lobjet que lon
souhaite ajouter la fin de la liste.
La mthode append, comme beaucoup de mthodes de listes, travaille directement sur lobjet et ne renvoie donc rien !
111

CHAPITRE 11. LES LISTES ET TUPLES (1/2)


Ceci est extrmement important. Dans le chapitre prcdent, nous avons vu quaucune
des mthodes de chanes ne modifie lobjet dorigine mais quelles renvoient toutes un
nouvel objet, qui est la chane modifie. Ici cest le contraire : les mthodes de listes ne
renvoient rien mais modifient lobjet dorigine. Regardez ce code si ce nest pas bien
clair :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

>>> chaine1 = " une petite phrase "


>>> chaine2 = chaine1 . upper () # On met en majuscules chaine1
>>> chaine1
# On affiche la cha ne d origine
une petite phrase
>>> # Elle n a pas t modifi e par la m thode upper
... chaine2
# On affiche chaine2
UNE PETITE PHRASE
>>> # C est chaine2 qui contient la cha ne en majuscules
... # Voyons pour les listes pr sent
... liste1 = [1 , 5.5 , 18]
>>> liste2 = liste1 . append ( -15) # On ajoute -15 liste1
>>> liste1
# On affiche liste1
[1 , 5.5 , 18 , -15]
>>> # Cette fois , l appel de la m thode a modifi l objet d
origine ( liste1 )
... # Voyons ce que contient liste2
... liste2
>>> # Rien ? V rifions avec print
... print ( liste2 )
None
>>>

Je vais expliquer les dernires lignes. Mais dabord, il faut que vous fassiez bien la
diffrence entre les mthodes de chanes, o lobjet dorigine nest jamais modifi et
qui renvoient un nouvel objet, et les mthodes de listes, qui ne renvoient rien mais
modifient lobjet dorigine.
Jai dit que les mthodes de listes ne renvoient rien. On va pourtant essayer de capturer la valeur de retour dans liste2. Quand on essaye dafficher la valeur de liste2
par saisie directe, on nobtient rien. Il faut lafficher avec print pour savoir ce quelle
contient : None. Cest lobjet vide de Python. En ralit, quand une fonction ne renvoie
rien, elle renvoie None. Vous retrouverez peut-tre cette valeur de temps autre, ne
soyez donc pas surpris.
Insrer un lment dans la liste
Nous allons passer assez rapidement sur cette seconde mthode. On peut, trs simplement, insrer un objet dans une liste, lendroit voulu. On utilise pour cela la mthode
insert.
1
2
3

112

>>> ma_liste = [ a , b , d , e ]
>>> ma_liste . insert (2 , c ) # On ins re c l indice 2
>>> print ( ma_liste )

CRONS ET DITONS NOS PREMIRES LISTES


4

[ a , b , c , d , e ]

Quand on demande dinsrer c lindice 2, la mthode va dcaler les objets dindice


suprieur ou gal 2. c va donc sintercaler entre b et d.
Concatnation de listes
On peut galement agrandir des listes en les concatnant avec dautres.
1
2
3
4
5
6
7
8
9
10
11
12

>>> ma_liste1 = [3 , 4 , 5]
>>> ma_liste2 = [8 , 9 , 10]
>>> ma_liste1 . extend ( ma_liste2 ) # On ins re ma_liste2 la fin
de ma_liste1
>>> print ( ma_liste1 )
[3 , 4 , 5 , 8 , 9 , 10]
>>> ma_liste1 = [3 , 4 , 5]
>>> ma_liste1 + ma_liste2
[3 , 4 , 5 , 8 , 9 , 10]
>>> ma_liste1 += ma_liste2 # Identique extend
>>> print ( ma_liste1 )
[3 , 4 , 5 , 8 , 9 , 10]
>>>

Voici les diffrentes faons de concatner des listes. Vous pouvez remarquer loprateur
+ qui concatne deux listes entre elles et renvoie le rsultat. On peut utiliser += assez
logiquement pour tendre une liste. Cette faon de faire revient au mme quutiliser la
mthode extend.

Suppression dlments dune liste


Nous allons voir rapidement comment supprimer des lments dune liste, avant dapprendre les parcourir. Vous allez vite pouvoir constater que cela se fait assez simplement. Nous allons voir deux mthodes pour supprimer des lments dune liste :
le mot-cl del ;
la mthode remove.
Le mot-cl del
Cest un des mots-cls de Python, que jaurais pu vous montrer plus tt. Mais les
applications de del me semblaient assez peu pratiques avant daborder les listes.
del (abrviation de delete) signifie supprimer en anglais. Son utilisation est des
plus simple : del variable_a_supprimer. Voyons un exemple.
1
2

>>> variable = 34
>>> variable

113

CHAPITRE 11. LES LISTES ET TUPLES (1/2)


3
4
5
6
7
8
9

34
>>> del variable
>>> variable
Traceback ( most recent call last ) :
File " < stdin >" , line 1 , in < module >
NameError : name variable is not defined
>>>

Comme vous le voyez, aprs lutilisation de del, la variable nexiste plus. Python lefface
tout simplement. Mais on peut galement utiliser del pour supprimer des lments
dune squence, comme une liste, et cest ce qui nous intresse ici.
1
2
3
4
5
6
7
8

>>> ma_liste = [ -5 , -2 , 1 , 4 , 7 , 10]


>>> del ma_liste [0] # On supprime le premier l ment de la
liste
>>> ma_liste
[ -2 , 1 , 4 , 7 , 10]
>>> del ma_liste [2] # On supprime le troisi me l ment de la
liste
>>> ma_liste
[ -2 , 1 , 7 , 10]
>>>

La mthode remove
On peut aussi supprimer des lments de la liste grce la mthode remove qui prend
en paramtre non pas lindice de llment supprimer, mais llment lui-mme.
1
2
3
4
5

>>> ma_liste = [31 , 32 , 33 , 34 , 35]


>>> ma_liste . remove (32)
>>> ma_liste
[31 , 33 , 34 , 35]
>>>

La mthode remove parcourt la liste et en retire llment que vous lui passez en
paramtre. Cest une faon de faire un peu diffrente et vous appliquerez del ou remove
en fonction de la situation.
La mthode remove ne retire que la premire occurrence de la valeur trouve
dans la liste !
Notez au passage que le mot-cl del nest pas une mthode de liste. Il sagit dune
fonctionnalit de Python quon retrouve dans la plupart des objets conteneurs, tels
que les listes que nous venons de voir, ou les dictionnaires que nous verrons plus tard.
Dailleurs, del sert plus gnralement supprimer non seulement des lments dune
squence mais aussi, comme nous lavons vu, des variables.
114

LE PARCOURS DE LISTES
Nous allons prsent voir comment parcourir une liste, mme si vous devez dj avoir
votre petite ide sur la question.

Le parcours de listes
Vous avez dj d vous faire une ide des mthodes pour parcourir une liste. Je vais
passer brivement dessus, vous ne verrez rien de nouveau ni, je lespre, de trs surprenant.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

>>>
>>>
>>>
...
...
...
a
b
c
d
e
f
g
h
>>>
...

ma_liste = [ a , b , c , d , e , f , g , h ]
i = 0 # Notre indice pour la boucle while
while i < len ( ma_liste ) :
print ( ma_liste [ i ])
i += 1 # On incr mente i , ne pas oublier !

# Cette m thode est cependant pr f rable


for elt in ma_liste : # elt va prendre les valeurs
successives des l ments de ma_liste
...
print ( elt )
...
a
b
c
d
e
f
g
h
>>>

Il sagit des mmes mthodes de parcours que nous avons vues pour les chanes de
caractres, au chapitre prcdent. Nous allons cependant aller un peu plus loin.

La fonction enumerate
Les deux mthodes que nous venons de voir possdent toutes deux des inconvnients :
la mthode utilisant while est plus longue crire, moins intuitive et elle est permable aux boucles infinies, si lon oublie dincrmenter la variable servant de comp115

CHAPITRE 11. LES LISTES ET TUPLES (1/2)


teur ;
la mthode par for se contente de parcourir la liste en capturant les lments dans
une variable, sans quon puisse savoir o ils sont dans la liste.
Cest vrai dans le cas que nous venons de voir. Certains codeurs vont combiner les deux
mthodes pour plus de flexibilit mais, trs souvent, le code obtenu est moins lisible.
Heureusement, les dveloppeurs de Python ont pens nous.
1
2
3
4
5
6
7
8
9
10
11
12
13

>>> ma_liste = [ a , b , c , d , e , f , g , h ]
>>> for i , elt in enumerate ( ma_liste ) :
...
print (" l indice {} se trouve {}.". format (i , elt ) )
...
l indice 0 se trouve a .
l indice 1 se trouve b .
l indice 2 se trouve c .
l indice 3 se trouve d .
l indice 4 se trouve e .
l indice 5 se trouve f .
l indice 6 se trouve g .
l indice 7 se trouve h .
>>>

Pas de panique !
Nous avons ici une boucle for un peu surprenante. Entre for et in, nous avons deux
variables, spares par une virgule.
En fait, enumerate prend en paramtre une liste et renvoie un objet qui peut tre
associ une liste contenant deux valeurs par lment : lindice et llment de la liste
parcouru.
Ce nest sans doute pas encore trs clair. Essayons dafficher cela un peu mieux :
1
2
3
4
5
6
7
8
9
10
11
12

>>>
...
...
(0 ,
(1 ,
(2 ,
(3 ,
(4 ,
(5 ,
(6 ,
(7 ,
>>>

for elt in enumerate ( ma_liste ) :


print ( elt )
a )
b )
c )
d )
e )
f )
g )
h )

Quand on parcourt chaque lment de lobjet renvoy par enumerate, on voit des
tuples qui contiennent deux lments : dabord lindice, puis lobjet se trouvant cet
indice dans la liste passe en argument la fonction enumerate.
116

LE PARCOURS DE LISTES
Les tuples sont des squences, assez semblables aux listes, sauf quon ne peut
modifier un tuple aprs quil ait t cr. Cela signifie quon dfinit le contenu
dun tuple (les objets quil doit contenir) lors de sa cration, mais quon ne
peut en ajouter ou en retirer par la suite.
Si les parenthses vous dconcertent trop, vous pouvez imaginer, la place, des crochets : dans cet exemple, cela revient au mme.
Quand on utilise enumerate, on capture lindice et llment dans deux variables distinctes. Voyons un autre exemple pour comprendre ce mcanisme :
1
2
3
4
5
6
7
8
9
10
11
12
13
14

>>> autre_liste = [
...
[1 , a ] ,
...
[4 , d ] ,
...
[7 , g ] ,
...
[26 , z ] ,
... ] # J ai tal la liste sur plusieurs lignes
>>> for nb , lettre in autre_liste :
...
print (" La lettre {} est la {} e de l alphabet .". format (
lettre , nb ) )
...
La lettre a est la 1 e de l alphabet .
La lettre d est la 4 e de l alphabet .
La lettre g est la 7 e de l alphabet .
La lettre z est la 26 e de l alphabet .
>>>

Jespre que cest assez clair dans votre esprit. Dans le cas contraire, dcomposez ces
exemples, le dclic devrait se faire.
On crit ici la dfinition de la liste sur plusieurs lignes pour des raisons de
lisibilit. On nest pas oblig de mettre des anti-slashs \ en fin de ligne
car, tant que Python ne trouve pas de crochet fermant la liste, il continue
dattendre sans interprter la ligne. Vous pouvez dailleurs le constater avec
les points qui remplacent les chevrons au dbut de la ligne, tant que la liste
na pas t referme.
Quand on travaille sur une liste que lon parcourt en mme temps, on peut
se retrouver face des erreurs assez tranges, qui paraissent souvent incomprhensibles au dbut.
Par exemple, on peut tre confront des exceptions IndexError si on tente de supprimer certains lments dune liste en la parcourant.
Nous verrons au prochain chapitre comment faire cela proprement, pour lheure il vous
suffit de vous mfier dun parcours qui modifie une liste, surtout sa structure. Dune
faon gnrale, vitez de parcourir une liste dont la taille volue en mme temps.
117

CHAPITRE 11. LES LISTES ET TUPLES (1/2)


Allez ! On va jeter un coup dil aux tuples, pour conclure ce chapitre !

Un petit coup dil aux tuples


Nous avons brivement vu les tuples un peu plus haut, grce la fonction enumerate.
Les tuples sont des listes immuables, quon ne peut modifier. En fait, vous allez vous
rendre compte que nous utilisons depuis longtemps des tuples sans nous en rendre
compte.
Un tuple se dfinit comme une liste, sauf quon utilise comme dlimiteur des parenthses
au lieu des crochets.
tuple_vide = ()
tuple_non_vide = (1 ,)
tuple_non_vide = (1 , 3 , 5 )

1
2
3

la diffrence des listes, les tuples, une fois crs, ne peuvent tre modifis : on ne
peut plus y ajouter dobjet ou en retirer.
Une petite subtilit ici : si on veut crer un tuple contenant un unique lment, on doit
quand mme mettre une virgule aprs celui-ci. Sinon, Python va automatiquement
supprimer les parenthses et on se retrouvera avec une variable lambda et non un tuple
contenant cette variable.
Mais quoi cela sert-il ?

Il est assez rare que lon travaille directement sur des tuples. Cest, aprs tout, un
type que lon ne peut pas modifier. On ne peut supprimer dlments dun tuple, ni
en ajouter. Cela vous parat peut-tre encore assez abstrait mais il peut tre utile de
travailler sur des donnes sans pouvoir les modifier.
En attendant, voyons plutt les cas o nous avons utilis des tuples sans le savoir.

Affectation multiple
Tous les cas que nous allons voir sont des cas daffectation multiple. Vous vous souvenez ?
1
2
3
4
5
6

>>> a , b = 3 , 4
>>> a
3
>>> b
4
>>>

118

UN PETIT COUP DIL AUX TUPLES


On a galement utilis cette syntaxe pour permuter deux variables. Eh bien, cette
syntaxe passe par des tuples qui ne sont pas dclars explicitement. Vous pourriez
crire :
1
2

>>> (a , b ) = (3 , 4)
>>>

Quand Python trouve plusieurs variables ou valeurs spares par des virgules et sans
dlimiteur, il va les mettre dans des tuples. Dans le premier exemple, les parenthses
sont sous-entendues et Python comprend ce quil doit faire.

Une fonction renvoyant plusieurs valeurs


Nous ne lavons pas vu jusquici mais une fonction peut renvoyer deux valeurs ou mme
plus :
1
2
3

def decomposer ( entier , divise_par ) :


""" Cette fonction retourne la partie enti re et le reste de
entier / divise_par """

4
5
6
7

p_e = entier // divise_par


reste = entier % divise_par
return p_e , reste

Et on peut ensuite capturer la partie entire et le reste dans deux variables, au retour
de la fonction :
1
2
3
4
5
6

>>> partie_entiere , reste = decomposer (20 , 3)


>>> partie_entiere
6
>>> reste
2
>>>

L encore, on passe par des tuples sans que ce soit indiqu explicitement Python.
Si vous essayez de faire retour = decomposer(20, 3), vous allez capturer un tuple
contenant deux lments : la partie entire et le reste de 20 divis par 3.
Nous verrons plus loin dautres exemples de tuples et dautres utilisations. Je pense
que cela suffit pour cette fois.

En rsum
Une liste est une squence mutable pouvant contenir plusieurs autres objets.
Une liste se construit ainsi : liste = [element1, element2, elementN].
On peut insrer des lments dans une liste laide des mthodes append, insert
et extends.
119

CHAPITRE 11. LES LISTES ET TUPLES (1/2)


On peut supprimer des lments dune liste grce au mot-cl del ou la mthode
remove.
Un tuple est une squence pouvant contenir des objets. la diffrence de la liste, le
tuple ne peut tre modifi une fois cr.

120

Chapitre

12

Les listes et tuples (2/2)


Difficult :
es listes sont trs utilises en Python. Elles sont lies pas mal de fonctionnalits, dont
certaines plutt complexes. Aussi ai-je prfr scinder lapproche des listes en deux
chapitres. Vous allez voir dans celui-ci quelques fonctionnalits qui ne sappliquent
quaux listes et aux tuples, et qui pourront vous tre extrmement utiles. Je vous conseille
donc, avant tout, dtre bien laise avec les listes et leur cration, parcours, dition,
suppression. . .

Dautre part, comme pour la plupart des sujets abords, je ne peux faire un tour dhorizon
exhaustif de toutes les fonctionnalits de chaque objet prsent. Je vous invite donc lire la
documentation, en tapant help(list), pour accder une liste exhaustive des mthodes.
Cest parti !

121

CHAPITRE 12. LES LISTES ET TUPLES (2/2)

Entre chanes et listes


Nous allons voir un moyen de transformer des chanes en listes et rciproquement.
Il est assez surprenant, de prime abord, quune conversion soit possible entre ces deux
types qui sont tout de mme assez diffrents. Mais comme on va le voir, il ne sagit pas
rellement dune conversion. Il va tre difficile de dmontrer lutilit de cette fonctionnalit tout de suite, mieux valent quelques exemples.

Des chanes aux listes


Pour convertir une chane en liste, on va utiliser une mthode de chane nomme
split ( clater en anglais). Cette mthode prend un paramtre qui est une autre
chane, souvent dun seul caractre, dfinissant comment on va dcouper notre chane
initiale.
Cest un peu compliqu et cela parat trs tordu. . . mais regardez plutt :
1
2
3
4

>>> ma_chaine = " Bonjour tous "


>>> ma_chaine . split (" ")
[ Bonjour , , tous ]
>>>

On passe en paramtre de la mthode split une chane contenant un unique espace.


La mthode renvoie une liste contenant les trois mots de notre petite phrase. Chaque
mot se trouve dans une case de la liste.
Cest assez simple en fait : quand on appelle la mthode split, celle-ci dcoupe la
chane en fonction du paramtre donn. Ici la premire case de la liste va donc du
dbut de la chane au premier espace (non inclus), la deuxime case va du premier
espace au second, et ainsi de suite jusqu la fin de la chane.
Sachez que split possde un paramtre par dfaut, un code qui reprsente les espaces,
les tabulations et les sauts de ligne. Donc vous pouvez trs bien faire ma_chaine.split(),
cela revient ici au mme.

Des listes aux chanes


Voyons linverse prsent, cest--dire si on a une liste contenant plusieurs chanes de
caractres que lon souhaite fusionner en une seule. On utilise la mthode de chane
join ( joindre en anglais). Sa syntaxe est un peu surprenante :
1
2
3
4

>>> ma_liste = [ Bonjour , , tous ]


>>> " ". join ( ma_liste )
Bonjour tous
>>>

122

ENTRE CHANES ET LISTES


En paramtre de la mthode join, on passe la liste des chanes que lon souhaite
ressouder . La mthode va travailler sur lobjet qui lappelle, ici une chane de
caractres contenant un unique espace. Elle va insrer cette chane entre chaque paire
de chanes de la liste, ce qui au final nous donne la chane de dpart, Bonjour tous .
Naurait-il pas t plus simple ou plus logique de faire une mthode de liste,
prenant en paramtre la chane faisant la jonction ?
Ce choix est en effet contest mais, pour ma part, je ne trancherai pas. Le fait est que
cest cette mthode qui a t choisie et, avec un peu dhabitude, on arrive bien lire le
rsultat obtenu. Dailleurs, nous allons voir comment appliquer concrtement ces deux
mthodes.

Une application pratique


Admettons que nous ayons un nombre flottant dont nous souhaitons afficher la partie
entire et les trois premires dcimales uniquement de la partie flottante. Autrement dit,
si on a un nombre flottant tel que 3.999999999999998 , on souhaite obtenir comme
rsultat 3.999 . Dailleurs, ce serait plus joli si on remplaait le point dcimal par la
virgule, laquelle nous sommes plus habitus.
L encore, je vous invite essayer de faire ce petit exercice par vous-mme. On part
du principe que la valeur de retour de la fonction charge de la pseudo-conversion est
une chane de caractres. Voici quelques exemples dutilisation de la fonction que vous
devriez coder :
1
2
3
4
5

>>> affich er_flottant (3.99999999999998)


3 ,999
>>> affich er_flottant (1.5)
1 ,5
>>>

Voici la correction que je vous propose :


1
2

def affi cher_flottant ( flottant ) :


""" Fonction prenant en param tre un flottant et renvoyant
une cha ne de caract res repr sentant la troncature de
ce nombre . La partie flottante doit avoir une longueur
maximum de 3 caract res .

3
4

De plus , on va remplacer le point d cimal par la virgule """

5
6
7
8
9

if type ( flottant ) is not float :


raise TypeError ( " Le param tre attendu doit tre un
flottant " )
flottant = str ( flottant )
partie_entiere , partie_flottante = flottant . split ( " . " )

123

CHAPITRE 12. LES LISTES ET TUPLES (2/2)


# La partie enti re n ' est pas modifier
# Seule la partie flottante doit tre tronqu e
return " ," . join ([ partie_entiere , partie_flottante [: 3 ]])

10
11
12

En sassurant que le type pass en paramtre est bien un flottant, on garantit quil
ny aura pas derreur lors du fractionnement de la chane. On est sr quil y aura
forcment une partie entire et une partie flottante spares par un point, mme si la
partie flottante nest constitue que dun 0. Si vous ny tes pas arrivs par vous-mme,
tudiez bien cette solution, elle nest pas forcment vidente au premier coup dil. On
fait intervenir un certain nombre de mcanismes que vous avez vus il y a peu, tchez
de bien les comprendre.

Les listes et paramtres de fonctions


Nous allons droit vers une fonctionnalit des plus intressantes, qui fait une partie de la
puissance de Python. Nous allons tudier un cas assez particulier avant de gnraliser :
les fonctions dont le nombre de paramtres est inconnu.
Notez malgr tout que ce point est assez dlicat. Si vous narrivez pas bien le comprendre, laissez cette section de ct, cela ne vous pnalisera pas.

Les fonctions dont on ne connat pas lavance le nombre de


paramtres
Vous devriez tout de suite penser la fonction print : on lui passe une liste de paramtres quelle va afficher, dans lordre o ils sont placs, spars par un espace (ou
tout autre dlimiteur choisi).
Vous nallez peut-tre pas trouver dapplications de cette fonctionnalit dans limmdiat mais, tt ou tard, cela arrivera. La syntaxe est tellement simple que cen est
dconcertant :
1

def fonction (* parametres ) :

On place une toile * devant le nom du paramtre qui accueillera la liste des arguments.
Voyons plus prcisment comment cela se prsente :
1
2
3
4
5
6
7
8
9
10

>>> def fonction_inconnue (* parametres ) :


...
""" Test d une fonction pouvant tre appel e avec un
nombre variable de param tres """
...
...
print (" J ai re u : {}.". format ( parametres ) )
...
>>> fonct ion_inconnue () # On appelle la fonction sans param tre
J ai re u : () .
>>> fonct ion_inconnue (33)
J ai re u : (33 ,) .
>>> fonct ion_inconnue ( a , e , f )

124

LES LISTES ET PARAMTRES DE FONCTIONS


11
12
13
14
15

J ai re u : ( a , e , f ) .
>>> var = 3.5
>>> foncti on_inconnue ( var , [4] , " ... ")
J ai re u : (3.5 , [4] , ... ) .
>>>

Je pense que cela suffit. Comme vous le voyez, on peut appeler la fonction_inconnue
avec un nombre indtermin de paramtres, allant de 0 linfini (enfin, thoriquement).
Le fait de prciser une toile * devant le nom du paramtre fait que Python va placer
tous les paramtres de la fonction dans un tuple, que lon peut ensuite traiter comme
on le souhaite.
Et les paramtres nomms dans lhistoire ? Comment sont-ils insrs dans le
tuple ?
Ils ne le sont pas. Si vous tapez fonction_inconnue(couleur="rouge"), vous allez avoir une erreur : fonction_inconnue() got an unexpected keyword argument
couleur. Nous verrons au prochain chapitre comment capturer ces paramtres nomms.
Vous pouvez bien entendu dfinir une fonction avec plusieurs paramtres qui doivent
tre fournis quoi quil arrive, suivis dune liste de paramtres variables :
1

def fonc tion_inconnue ( nom , prenom , * commentaires ) :

Dans cet exemple de dfinition de fonction, vous devez imprativement prciser un


nom et un prnom, et ensuite vous mettez ce que vous voulez en commentaire, aucun
paramtre, un, deux. . . ce que vous voulez.
Si on dfinit une liste variable de paramtres, elle doit se trouver aprs la liste
des paramtres standard.
Au fond, cela est vident. Vous ne pouvez avoir une dfinition de fonction comme
def fonction_inconnue(*parametres, nom, prenom). En revanche, si vous souhaitez avoir des paramtres nomms, il faut les mettre aprs cette liste. Les paramtres
nomms sont un peu une exception puisquils ne figureront de toute faon pas dans le
tuple obtenu. Voyons par exemple la dfinition de la fonction print :
1

print ( value , ... , sep = ' ' , end = '\ n ' , file = sys . stdout )

Ne nous occupons pas du dernier paramtre. Il dfinit le descripteur vers lequel print
envoie ses donnes ; par dfaut, cest lcran.
Do viennent ces points de suspension dans les paramtres ?

125

CHAPITRE 12. LES LISTES ET TUPLES (2/2)


En fait, il sagit dun affichage un peu plus agrable. Si on veut rellement avoir la
dfinition en code Python, on retombera plutt sur :
1

def print (* values , sep = ' ' , end = '\ n ' , file = sys . stdout ) :

Petit exercice : faire une fonction afficher identique print, cest--dire prenant un
nombre indtermin de paramtres, les affichant en les sparant laide du paramtre
nomm sep et terminant laffichage par la variable fin. Notre fonction afficher ne
comptera pas de paramtre file. En outre, elle devra passer par print pour afficher
(on ne connat pas encore dautres faons de faire). La seule contrainte est que lappel
print ne doit compter quun seul paramtre non nomm. Autrement dit, avant lappel
print, la chane devra avoir t dj formate, prte laffichage.
Pour que ce soit plus clair, je vous mets la dfinition de la fonction, ainsi que la
docstring que jai crite :
1
2

def afficher (* parametres , sep = ' ' , fin = '\ n ') :


""" Fonction charg e de reproduire le comportement de print .

3
4
5
6

Elle doit finir par faire appel print pour afficher le r


sultat .
Mais les param tres devront d j avoir t format s .
On doit passer print une unique cha ne , en lui sp cifiant
de ne rien mettre la fin :

7
8

print ( chaine , end = ' ') """

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

#
#
#
#

Les param tres sont sous la forme d ' un tuple


Or on a besoin de les convertir
Mais on ne peut pas modifier un tuple
On a plusieurs possibilit s , ici je choisis de convertir
le tuple en liste
parametres = list ( parametres )
# On va commencer par convertir toutes les valeurs en cha
ne
# Sinon on va avoir quelques probl mes lors du join
for i , parametre in enumerate ( parametres ) :
parametres [ i ] = str ( parametre )
# La liste des param tres ne contient plus que des cha nes
de caract res
# pr sent on va constituer la cha ne finale
chaine = sep . join ( parametres )
# On ajoute le param tre fin la fin de la cha ne
chaine += fin
# On affiche l ' ensemble
print ( chaine , end = ' ')

Jespre que ce ntait pas trop difficile et que, si vous avez fait des erreurs, vous avez
pu les comprendre.
Ce nest pas du tout grave si vous avez russi coder cette fonction dune manire
diffrente. En programmation, il ny a pas quune solution, il y a des solutions.
126

LES COMPRHENSIONS DE LISTE

Transformer une liste en paramtres de fonction


Cest peut-tre un peu moins frquent mais vous devez connatre ce mcanisme puisquil complte parfaitement le premier. Si vous avez un tuple ou une liste contenant
des paramtres qui doivent tre passs une fonction, vous pouvez trs simplement les
transformer en paramtres lors de lappel. Le seul problme cest que, ct dmonstration, je me vois un peu limit.

1
2
3
4

>>> l i s t e_ d e s _parametres = [1 , 4 , 9 , 16 , 25 , 36]


>>> print (* l iste_des_parametres )
1 4 9 16 25 36
>>>

Ce nest pas bien spectaculaire et pourtant cest une fonctionnalit trs puissante du
langage. L, on a une liste contenant des paramtres et on la transforme en une liste
de paramtres de la fonction print. Donc, au lieu dafficher la liste proprement dite,
on affiche tous les nombres, spars par des espaces. Cest exactement comme si vous
aviez fait print(1, 4, 9, 16, 25, 36).
Mais quel intrt ? Cela ne change pas grand-chose et il est rare que lon
capture les paramtres dune fonction dans une liste, non ?
Oui je vous laccorde. Ici lintrt ne saute pas aux yeux. Mais un peu plus tard,
vous pourrez tomber sur des applications o les fonctions sont utilises sans savoir
quels paramtres elles attendent rellement. Si on ne connat pas la fonction que lon
appelle, cest trs pratique. L encore, vous dcouvrirez cela dans les chapitres suivants
ou dans certains projets. Essayez de garder lesprit ce mcanisme de transformation.
On utilise une toile * dans les deux cas. Si cest dans une dfinition de fonction, cela
signifie que les paramtres fournis non attendus lors de lappel seront capturs dans la
variable, sous la forme dun tuple. Si cest dans un appel de fonction, au contraire, cela
signifie que la variable sera dcompose en plusieurs paramtres envoys la fonction.
Jespre que vous tes encore en forme, on attaque le point que je considre comme le
plus dur de ce chapitre, mais aussi le plus intressant. Gardez les yeux ouverts !

Les comprhensions de liste


Les comprhensions de liste ( list comprehensions en anglais) sont un moyen de
filtrer ou modifier une liste trs simplement. La syntaxe est dconcertante au dbut
mais vous allez voir que cest trs puissant.
127

CHAPITRE 12. LES LISTES ET TUPLES (2/2)

Parcours simple
Les comprhensions de liste permettent de parcourir une liste en en renvoyant une
seconde, modifie ou filtre. Pour linstant, nous allons voir une simple modification.
1
2
3
4

>>> liste_origine = [0 , 1 , 2 , 3 , 4 , 5]
>>> [ nb * nb for nb in liste_origine ]
[0 , 1 , 4 , 9 , 16 , 25]
>>>

tudions un peu la ligne 2 de ce code. Comme vous avez pu le deviner, elle signifie en
langage plus conventionnel Mettre au carr tous les nombres contenus dans la liste
dorigine . Nous trouvons dans lordre, entre les crochets qui sont les dlimiteurs dune
instruction de comprhension de liste :
nb * nb : la valeur de retour. Pour linstant, on ne sait pas ce quest la variable nb,
on sait juste quil faut la mettre au carr. Notez quon aurait pu crire nb**2, cela
revient au mme.
for nb in liste_origine : voil do vient notre variable nb. On reconnat la
syntaxe dune boucle for, sauf quon nest pas habitu la voir sous cette forme.
Quand Python interprte cette ligne, il va parcourir la liste dorigine et mettre chaque
lment de la liste au carr. Il renvoie ensuite le rsultat obtenu, sous la forme dune
liste qui est de la mme longueur que celle dorigine. On peut naturellement capturer
cette nouvelle liste dans une variable.

Filtrage avec un branchement conditionnel


On peut aussi filtrer une liste de cette faon :
1
2
3
4

>>> liste_origine = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10]


>>> [ nb for nb in liste_origine if nb %2==0]
[2 , 4 , 6 , 8 , 10]
>>>

On rajoute la fin de linstruction une condition qui va dterminer quelles valeurs


seront transfres dans la nouvelle liste. Ici, on ne transfre que les valeurs paires. Au
final, on se retrouve donc avec une liste deux fois plus petite que celle dorigine.

Mlangeons un peu tout cela


Il est possible de filtrer et modifier une liste assez simplement. Par exemple, on a une
liste contenant les quantits de fruits stockes pour un magasin (je ne suis pas sectaire,
vous pouvez prendre des hamburgers si vous prfrez). Chaque semaine, le magasin va
prendre dans le stock une certaine quantit de chaque fruit, pour la mettre en vente.
ce moment, le stock de chaque fruit diminue naturellement. Inutile, en consquence,
de garder les fruits quon na plus en stock.
128

LES COMPRHENSIONS DE LISTE


Je vais un peu reformuler. On va avoir une liste simple, qui contiendra des entiers,
prcisant la quantit de chaque fruit (cest abstrait, les fruits ne sont pas prciss). On
va faire une comprhension de liste pour diminuer dune quantit donne toutes les
valeurs de cette liste, et on en profite pour retirer celles qui sont infrieures ou gales
0.
1
2
3
4
5

>>> qtt_a_retirer = 7 # On retire chaque semaine 7 fruits de


chaque sorte
>>> fruits_stockes = [15 , 3 , 18 , 21] # Par exemple 15 pommes , 3
melons ...
>>> [ nb_fruits - qtt_a_retirer for nb_fruits in fruits_stockes if
nb_fruits > qtt_a_retirer ]
[8 , 11 , 14]
>>>

Comme vous le voyez, le fruit de quantit 3 na pas survcu cette semaine dachats.
Bien sr, cet exemple nest pas complet : on na aucun moyen fiable dassocier les
nombres restants aux fruits. Mais vous avez un exemple de filtrage et modification
dune liste.
Prenez bien le temps de regarder ces exemples : au dbut, la syntaxe des comprhensions
de liste nest pas forcment simple. Faites des essais, cest aussi le meilleur moyen de
comprendre.

Nouvelle application concrte


De nouveau, cest vous de travailler.
Nous allons en gros reprendre lexemple prcdent, en le modifiant un peu pour quil soit
plus cohrent. Nous travaillons toujours avec des fruits sauf que, cette fois, nous allons
associer un nom de fruit la quantit restant en magasin. Nous verrons au prochain
chapitre comment le faire avec des dictionnaires ; pour linstant on va se contenter de
listes :
1
2
3
4
5
6
7
8

>>> inventaire = [
...
(" pommes " , 22) ,
...
(" melons " , 4) ,
...
(" poires " , 18) ,
...
(" fraises " , 76) ,
...
(" prunes " , 51) ,
... ]
>>>

Recopiez cette liste. Elle contient des tuples, contenant chacun un couple : le nom du
fruit et sa quantit en magasin.
Votre mission est de trier cette liste en fonction de la quantit de chaque fruit. Autrement dit, on doit obtenir quelque chose de similaire :
1

129

CHAPITRE 12. LES LISTES ET TUPLES (2/2)


2
3
4
5
6
7

( " fraises " , 76 ) ,


( " prunes " , 51 ) ,
( " pommes " , 22 ) ,
( " poires " , 18 ) ,
( " melons " , 4 ) ,

Pour ceux qui nont pas eu la curiosit de regarder dans la documentation des listes, je
signale votre attention la mthode sort qui permet de trier une liste. Vous pouvez
galement utiliser la fonction sorted qui prend en paramtre la liste trier (ce nest
pas une mthode de liste, faites attention). sorted renvoie la liste trie sans modifier la
liste dorigine, ce qui peut tre utile dans certaines circonstances, prcisment celle-ci.
vous de voir, vous pouvez y arriver par les deux mthodes.
Bien entendu, essayez de faire cet exercice en utilisant les comprhensions de liste.
Je vous donne juste un petit indice : vous ne pouvez trier la liste comme cela, il faut
linverser (autrement dit, placer la quantit avant le nom du fruit) pour pouvoir ensuite
la trier par quantit. Un chapitre entier est consacr au tri en Python, vous verrez
dautres moyens pour trier plus efficacement. Mais en attendant, essayez de travailler
avec ce que vous savez faire.
Voici la correction que je vous propose :
1
2
3
4
5
6

# On change le sens de l ' inventaire , la quantit avant le nom


in ve nt air e_inverse = [( qtt , nom_fruit ) for nom_fruit , qtt in
inventaire ]
# On n 'a plus qu ' trier dans l ' ordre d croissant l ' inventaire
invers
# On reconstitue l ' inventaire tri
inventaire = [( nom_fruit , qtt ) for qtt , nom_fruit in sorted (
inventaire_inverse , \
reverse = True ) ]

Cela marche et le traitement a t fait en deux lignes.


Vous pouvez trier linventaire invers avant la reconstitution, si vous trouvez cela plus
comprhensible. Il faut privilgier la lisibilit du code.
1
2
3
4
5
6

# On change le sens de l ' inventaire , la quantit avant le nom


in ve nt air e_inverse = [( qtt , nom_fruit ) for nom_fruit , qtt in
inventaire ]
# On trie l ' inventaire invers dans l ' ordre d croissant
in ve nt air e_inverse . sort ( reverse = True )
# Et on reconstitue l ' inventaire
inventaire = [( nom_fruit , qtt ) for qtt , nom_fruit in
in ve ntaire_inverse ) ]

Faites des essais, entranez-vous, vous en aurez sans doute besoin, la syntaxe nest pas
trs simple au dbut. Et vitez de tomber dans lextrme aussi : certaines oprations ne
sont pas faisables avec les comprhensions de listes ou alors elles sont trop condenses
pour tre facilement comprhensibles. Dans lexemple prcdent, on aurait trs bien pu
130

LES COMPRHENSIONS DE LISTE


remplacer nos deux trois lignes dinstructions par une seule, mais cela aurait t dur
lire. Ne sacrifiez pas la lisibilit pour le simple plaisir de raccourcir votre code.

En rsum
On peut dcouper une chane en fonction dun sparateur en utilisant la mthode
split de la chane.
On peut joindre une liste contenant des chanes de caractres en utilisant la mthode
de chane join. Cette mthode doit tre appele sur le sparateur.
On peut crer des fonctions attendant un nombre inconnu de paramtres grce
la syntaxe def fonction_inconnue(*parametres): (les paramtres passs se retrouvent dans le tuple parametres).
Les comprhensions de listes permettent de parcourir et filtrer une squence en en
renvoyant une nouvelle.
La syntaxe pour effectuer un filtrage est la suivante : nouvelle_squence = [element
for element in ancienne_squence if condition].

131

CHAPITRE 12. LES LISTES ET TUPLES (2/2)

132

Chapitre

13

Les dictionnaires
Difficult :
aintenant que vous commencez vous familiariser avec la programmation oriente
objet, nous allons pouvoir aller un peu plus vite sur les manipulations classiques
de ce type, pour nous concentrer sur quelques petites spcificits propres aux dictionnaires.

Les dictionnaires sont des objets pouvant en contenir dautres, linstar des listes. Cependant, au lieu dhberger des informations dans un ordre prcis, ils associent chaque objet
contenu une cl (la plupart du temps, une chane de caractres). Par exemple, un dictionnaire peut contenir un carnet dadresses et on accde chaque contact en prcisant
son nom.

133

CHAPITRE 13. LES DICTIONNAIRES

Cration et dition de dictionnaires


Un dictionnaire est un type de donnes extrmement puissant et pratique. Il se rapproche des listes sur certains points mais, sur beaucoup dautres, il en diffre totalement.
Python utilise ce type pour reprsenter diverses fonctionnalits : on peut par exemple
retrouver les attributs dun objet grce un dictionnaire particulier.
Mais nanticipons pas. Dans les deux chapitres prcdents, nous avons dcouvert les
listes. Les objets de ce type sont des objets conteneurs, dans lesquels on trouve dautres
objets. Pour accder ces objets contenus, il faut connatre leur position dans la liste.
Cette position se traduit par des entiers, appels indices, compris entre 0 (inclus) et la
taille de la liste (non incluse). Tout cela, vous devez dj le savoir.
Le dictionnaire est aussi un objet conteneur. Il na quant lui aucune structure ordonne, la diffrence des listes. De plus, pour accder aux objets contenus dans le
dictionnaire, on nutilise pas ncessairement des indices mais des cls qui peuvent tre
de bien des types distincts.

Crer un dictionnaire
L encore, je vous donne le nom de la classe sur laquelle se construit un dictionnaire :
dict. Vous devriez du mme coup trouver la premire mthode dinstanciation dun
dictionnaire :
1
2
3
4
5
6
7
8
9
10

>>> mon_dictionnaire = dict ()


>>> type ( mon_dictionnaire )
< class dict >
>>> mon_dictionnaire
{}
>>> # Du coup , vous devriez trouver la deuxi me mani re de cr
er un dictionnaire vide
... mon_dictionnaire = {}
>>> mon_dictionnaire
{}
>>>

Les parenthses dlimitent les tuples, les crochets dlimitent les listes et les accolades
{} dlimitent les dictionnaires.
Voyons comment ajouter des cls et valeurs dans notre dictionnaire vide :
1
2
3
4
5
6

>>> mon_dictionnaire = {}
>>> mon_dictionnaire [" pseudo "] = " Prolixe "
>>> mon_dictionnaire [" mot de passe "] = "*"
>>> mon_dictionnaire
{ mot de passe : * , pseudo : Prolixe }
>>>

134

CRATION ET DITION DE DICTIONNAIRES


Nous indiquons entre crochets la cl laquelle nous souhaitons accder. Si la cl nexiste
pas, elle est ajoute au dictionnaire avec la valeur spcifie aprs le signe =. Sinon,
lancienne valeur lemplacement indiqu est remplace par la nouvelle :
1
2
3
4
5
6
7

>>> mon_dictionnaire = {}
>>> mon_dictionnaire [" pseudo "] = " Prolixe "
>>> mon_dictionnaire [" mot de passe "] = "*"
>>> mon_dictionnaire [" pseudo "] = "6 pri1 "
>>> mon_dictionnaire
{ mot de passe : * , pseudo : 6 pri1 }
>>>

La valeur Prolixe pointe par la cl pseudo a t remplace, la ligne 4, par


la valeur 6pri1. Cela devrait vous rappeler la cration de variables : si la variable
nexiste pas, elle est cre, sinon elle est remplace par la nouvelle valeur.
Pour accder la valeur dune cl prcise, cest trs simple :
1
2
3

>>> mon_dictionnaire [" mot de passe "]


*
>>>

Si la cl nexiste pas dans le dictionnaire, une exception de type KeyError sera leve.
Gnralisons un peu tout cela : nous avons des dictionnaires, qui peuvent contenir
dautres objets. On place ces objets et on y accde grce des cls. Un dictionnaire
ne peut naturellement pas contenir deux cls identiques (comme on la vu, la seconde
valeur crase la premire). En revanche, rien nempche davoir deux valeurs identiques
dans le dictionnaire.
Nous avons utilis ici, pour nos cls et nos valeurs, des chanes de caractres. Ce nest
absolument pas obligatoire. Comme avec les listes, vous pouvez utiliser des entiers
comme cls :
1
2
3
4
5
6
7
8
9
10

>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
{0:
>>>

mon_dictionnaire = {}
mon_dictionnaire [0] = " a "
mon_dictionnaire [1] = " e "
mon_dictionnaire [2] = " i "
mon_dictionnaire [3] = " o "
mon_dictionnaire [4] = " u "
mon_dictionnaire [5] = " y "
mon_dictionnaire
a , 1: e , 2: i , 3: o , 4: u , 5: y }

On a limpression de recrer le fonctionnement dune liste mais ce nest pas le cas :


rappelez-vous quun dictionnaire na pas de structure ordonne. Si vous supprimez par
exemple lindice 2, le dictionnaire, contrairement aux listes, ne va pas dcaler toutes
les cls dindice suprieur lindice supprim. Il na pas t conu pour.
135

CHAPITRE 13. LES DICTIONNAIRES


On peut utiliser quasiment tous les types comme cls et on peut utiliser absolument
tous les types comme valeurs.
Voici un exemple un peu plus atypique de cls : on souhaite reprsenter un plateau
dchecs. Traditionnellement, on reprsente une case de lchiquier par une lettre (de
A H) suivie dun chiffre (de 1 8). La lettre dfinit la colonne et le chiffre dfinit la
ligne. Si vous ntes pas srs de comprendre, regardez la figure 13.1.

Figure 13.1 chiquier


Pourquoi ne pas faire un dictionnaire dont les cls seront des tuples contenant la lettre
et le chiffre identifiant la case, auxquelles on associe comme valeurs le nom des pices ?
1
2
3
4
5
6
7
8
9

echiquier = { }
echiquier [ 'a ' , 1 ] = " tour blanche " # En bas gauche de l '
chiquier
echiquier [ 'b ' , 1 ] = " cavalier blanc " # droite de la tour
echiquier [ 'c ' , 1 ] = " fou blanc " # droite du cavalier
echiquier [ 'd ' , 1 ] = " reine blanche " # droite du fou
# ... Premi re ligne des blancs
echiquier [ 'a ' , 2 ] = " pion blanc " # Devant la tour
echiquier [ 'b ' , 2 ] = " pion blanc " # Devant le cavalier , droite
du pion
# ... Seconde ligne des blancs

Dans cet exemple, nos tuples sont sous-entendus. On ne les place pas entre parenthses.
Python comprend quon veut crer des tuples, ce qui est bien, mais limportant est
que vous le compreniez bien aussi. Certains cours encouragent toujours placer des
parenthses autour des tuples quand on les utilise. Pour ma part, je pense que, si vous
gardez lesprit quil sagit de tuples, que vous navez aucune peine lidentifier, cela
136

CRATION ET DITION DE DICTIONNAIRES


suffit. Si vous faites la confusion, mettez des parenthses autour des tuples en toutes
circonstances.
On peut aussi crer des dictionnaires dj remplis :
1

placard = { " chemise " :3 , " pantalon " :6 , " tee - shirt " : 7 }

On prcise entre accolades la cl, le signe deux points : et la valeur correspondante.


On spare les diffrents couples cl : valeur par une virgule. Cest dailleurs comme
cela que Python vous affiche un dictionnaire quand vous le lui demandez.
Certains ont peut-tre essay de crer des dictionnaires dj remplis avant que je ne
montre comment faire. Une petite prcision, si vous avez tap une instruction similaire
:
1

mon_dictionnaire = { ' pseudo ' , ' mot de passe '}

Avec une telle instruction, ce nest pas un dictionnaire que vous crez, mais un set.
Un set (ensemble) est un objet conteneur (lui aussi), trs semblable aux listes sauf
quil ne peut contenir deux objets identiques. Vous ne pouvez pas trouver deux fois
dans un set lentier 3 par exemple. Je vous laisse vous renseigner sur les sets si vous
le dsirez.

Supprimer des cls dun dictionnaire


Comme pour les listes, vous avez deux possibilits mais elles reviennent sensiblement
au mme :
le mot-cl del ;
la mthode de dictionnaire pop.
Je ne vais pas mattarder sur le mot-cl del, il fonctionne de la mme faon que pour
les listes :
1
2

placard = { " chemise " :3 , " pantalon " :6 , " tee shirt " : 7 }
del placard [ " chemise " ]

La mthode pop supprime galement la cl prcise mais elle renvoie la valeur supprime :
1
2
3
4

>>> placard = {" chemise ":3 , " pantalon ":6 , " tee shirt ":7}
>>> placard . pop (" chemise ")
3
>>>

En plus de supprimer la cl et la valeur associe, la mthode pop renvoie la valeur qui


a t supprime en mme temps que la cl. Cela peut tre utile parfois.
Voil pour le tour dhorizon. Ce fut bref et vous navez pas vu toutes les mthodes,
bien entendu. Je vous laisse consulter laide pour une liste dtaille.
137

CHAPITRE 13. LES DICTIONNAIRES

Un peu plus loin


On se sert parfois des dictionnaires pour stocker des fonctions.
Je vais juste vous montrer rapidement le mcanisme sans trop my attarder. L, je
compte sur vous pour faire des tests si vous tes intresss. Cest encore un petit
quelque chose que vous nutiliserez peut-tre pas tous les jours mais quil peut tre
utile de connatre.
Les fonctions sont manipulables comme des variables. Ce sont des objets, un peu particuliers mais des objets tout de mme. Donc on peut les prendre pour valeur daffectation ou les ranger dans des listes ou dictionnaires. Cest pourquoi je prsente cette
fonctionnalit prsent, auparavant jaurais manqu dexemples pratiques.
>>> print_2 = print # L objet print_2 pointera sur la fonction
print
>>> print_2 (" Affichons un message ")
Affichons un message
>>>

1
2
3
4

On copie la fonction print dans une autre variable print_2. On peut ensuite appeler
print_2 et la fonction va afficher le texte saisi, tout comme print laurait fait.
En pratique, on affecte rarement des fonctions de cette manire. Cest peu utile. Par
contre, on met parfois des fonctions dans des dictionnaires :
1
2
3
4
5
6
7
8
9
10
11
12
13
14

>>> def fete () :


...
print (" C est la f te .")
...
>>> def oiseau () :
...
print (" Fais comme l oiseau ... ")
...
>>> fonctions = {}
>>> fonctions [" fete "] = fete # on ne met pas les parenth ses
>>> fonctions [" oiseau "] = oiseau
>>> fonctions [" oiseau "]
< function oiseau at 0 x00BA5198 >
>>> fonctions [" oiseau "]() # on essaye de l appeler
Fais comme l oiseau ...
>>>

Prenons dans lordre si vous le voulez bien :


On commence par dfinir deux fonctions, fete et oiseau (pardonnez lexemple).
On cre un dictionnaire nomm fonctions.
On met dans ce dictionnaire les fonctions fete et oiseau. La cl pointant vers la
fonction est le nom de la fonction, tout btement, mais on aurait pu lui donner un
nom plus original.
On essaye daccder la fonction oiseau en tapant fonctions[ oiseau ]. Python
nous renvoie un truc assez moche, <function oiseau at 0x00BA5198>, mais vous
138

LES MTHODES DE PARCOURS


comprenez lide : cest bel et bien notre fonction oiseau. Toutefois, pour lappeler,
il faut des parenthses, comme pour toute fonction qui se respecte.
En tapant fonctions["oiseau"](), on accde la fonction oiseau et on lappelle
dans la foule.
On peut stocker les rfrences des fonctions dans nimporte quel objet conteneur, des
listes, des dictionnaires. . . et dautres classes, quand nous apprendrons en faire. Je
ne vous demande pas de comprendre absolument la manipulation des rfrences des
fonctions, essayez simplement de retenir cet exemple. Dans tous les cas, nous aurons
loccasion dy revenir.

Les mthodes de parcours


Comme vous pouvez le penser, le parcours dun dictionnaire ne seffectue pas tout
fait comme celui dune liste. La diffrence nest pas si norme que cela mais, la plupart
du temps, on passe par des mthodes de dictionnaire.

Parcours des cls


Peut-tre avez-vous dj essay par vous-mmes de parcourir un dictionnaire comme
on la fait pour les listes :
1
2
3
4
5
6
7
8

>>> fruits = {" pommes ":21 , " melons ":3 , " poires ":31}
>>> for cle in fruits :
...
print ( cle )
...
melons
poires
pommes
>>>

Comme vous le voyez, si on essaye de parcourir un dictionnaire simplement , on


parcourt en ralit la liste des cls contenues dans le dictionnaire.
Mais. . . les cls ne saffichent pas dans lordre dans lequel on les a entres. . .
cest normal ?
Les dictionnaires nont pas de structure ordonne, gardez-le lesprit. Donc en ce sens
oui, cest tout fait normal.
Une mthode de la classe dict permet dobtenir ce mme rsultat. Personnellement,
je lutilise plus frquemment car on est sr, en lisant linstruction, que cest la liste des
cls que lon parcourt :
1

>>> fruits = {" pommes ":21 , " melons ":3 , " poires ":31}

139

CHAPITRE 13. LES DICTIONNAIRES


>>> for cle in fruits . keys () :
...
print ( cle )
...
melons
poires
pommes
>>>

2
3
4
5
6
7
8

La mthode keys ( cls en anglais) renvoie la liste des cls contenues dans le dictionnaire. En vrit, ce nest pas tout fait une liste (essayez de taper fruits.keys()
dans votre interprteur) mais cest une squence qui se parcourt comme une liste.

Parcours des valeurs


On peut aussi parcourir les valeurs contenues dans un dictionnaire. Pour ce faire, on
utilise la mthode values ( valeurs en anglais).
1
2
3
4
5
6
7
8

>>> fruits = {" pommes ":21 , " melons ":3 , " poires ":31}
>>> for valeur in fruits . values () :
...
print ( valeur )
...
3
31
21
>>>

Cette mthode est peu utilise pour un parcours car il est plus pratique de parcourir
la liste des cls, cela suffit pour avoir les valeurs correspondantes. Mais on peut aussi,
bien entendu, lutiliser dans une condition :
1
2
3
4
5

>>> if 21 in fruits . values () :


...
print (" Un des fruits se trouve dans la quantit 21.")
...
Un des fruits se trouve dans la quantit 21.
>>>

Parcours des cls et valeurs simultanment


Pour avoir en mme temps les indices et les objets dune liste, on utilise la fonction
enumerate, jespre que vous vous en souvenez. Pour faire de mme avec les dictionnaires, on utilise la mthode items. Elle renvoie une liste, contenant les couples cl :
valeur, sous la forme dun tuple. Voyons comment lutiliser :
1
2
3

140

>>> fruits = {" pommes ":21 , " melons ":3 , " poires ":31}
>>> for cle , valeur in fruits . items () :
...
print (" La cl {} contient la valeur {}.". format ( cle ,
valeur ) )

LES DICTIONNAIRES ET PARAMTRES DE FONCTION


4
5
6
7
8

...
La cl melons contient la valeur 3.
La cl poires contient la valeur 31.
La cl pommes contient la valeur 21.
>>>

Il est parfois trs pratique de parcourir un dictionnaire avec ses cls et les valeurs
associes.
Entranez-vous, il ny a que cela de vrai. Pourquoi pas reprendre lexercice du chapitre
prcdent, avec notre inventaire de fruits ? Sauf que le type de linventaire ne serait pas
une liste mais un dictionnaire associant les noms des fruits aux quantits ?
Il nous reste une petite fonctionnalit supplmentaire voir et on en aura fini avec les
dictionnaires.

Les dictionnaires et paramtres de fonction


Cela ne vous rappelle pas quelque chose ? Jespre bien que si, on a vu quelque chose
de similaire au chapitre prcdent.
Si vous vous souvenez, on avait russi intercepter tous les paramtres de la fonction. . .
sauf les paramtres nomms.

Rcuprer les paramtres nomms dans un dictionnaire


Il existe aussi une faon de capturer les paramtres nomms dune fonction. Dans ce
cas, toutefois, ils sont placs dans un dictionnaire. Si, par exemple, vous appelez la
fonction ainsi : fonction(parametre=a), vous aurez, dans le dictionnaire capturant
les paramtres nomms, une cl parametre lie la valeur a. Voyez plutt :
1
2
3
4
5
6
7
8
9
10
11
12

>>> def fonction_inconnue (** parametres_nommes ) :


...
""" Fonction permettant de voir comment r cup rer les
param tres nomm s
...
dans un dictionnaire """
...
...
...
print (" J ai re u en param tres nomm s : {}.". format (
param etres_nommes ) )
...
>>> foncti on_inconnue () # Aucun param tre
J ai re u en param tres nomm s : {}
>>> foncti on_inconnue ( p =4 , j =8)
J ai re u en param tres nomm s : { p : 4 , j : 8}
>>>

Pour capturer tous les paramtres nomms non prciss dans un dictionnaire, il faut
mettre deux toiles ** avant le nom du paramtre.
141

CHAPITRE 13. LES DICTIONNAIRES


Si vous passez des paramtres non nomms cette fonction, Python lvera une exception.
Ainsi, pour avoir une fonction qui accepte nimporte quel type de paramtres, nomms
ou non, dans nimporte quel ordre, dans nimporte quelle quantit, il faut la dclarer
de cette manire :
1

def fonc tion_inconnue (* en_liste , ** en_dictionnaire ) :

Tous les paramtres non nomms se retrouveront dans la variable en_liste et les
paramtres nomms dans la variable en_dictionnaire.
Mais quoi cela peut-il bien servir davoir une fonction qui accepte nimporte
quel paramtre ?
Pour linstant pas grand chose mais cela viendra. Quand on abordera le chapitre sur
les dcorateurs, vous vous en souviendrez et vous pourrez vous fliciter de connatre
cette fonctionnalit.

Transformer un dictionnaire en paramtres nomms dune fonction


L encore, on peut faire exactement linverse : transformer un dictionnaire en paramtres nomms dune fonction. Voyons un exemple tout simple :
1
2
3
4

>>> parametres = {" sep ":" >> " , " end ":" -\ n "}
>>> print (" Voici " , " un " , " exemple " , "d appel " , ** parametres )
Voici >> un >> exemple >> d appel >>>

Les paramtres nomms sont transmis la fonction par un dictionnaire. Pour indiquer
Python que le dictionnaire doit tre transmis comme des paramtres nomms, on
place deux toiles avant son nom ** dans lappel de la fonction.
Comme vous pouvez le voir, cest comme si nous avions crit :
1
2
3

>>> print (" Voici " , " un " , " exemple " , "d appel " , sep =" >> " , end =
-\ n ")
Voici >> un >> exemple >> d appel >>>

Pour linstant, vous devez trouver que cest bien se compliquer la vie pour si peu. Nous
verrons dans la suite de ce cours quil nen est rien, en fait, mme si nous nutilisons
pas cette fonctionnalit tous les jours.
142

LES DICTIONNAIRES ET PARAMTRES DE FONCTION

En rsum
Un dictionnaire est un objet conteneur associant des cls des valeurs.
Pour crer un dictionnaire, on utilise la syntaxe dictionnaire = {cle1:valeur1,
cle2=valeur2, cleN=valeurN}.
On peut ajouter ou remplacer un lment dans un dictionnaire : dictionnaire[cle]
= valeur.
On peut supprimer une cl (et sa valeur correspondante) dun dictionnaire en utilisant, au choix, le mot-cl del ou la mthode pop.
On peut parcourir un dictionnaire grce aux mthodes keys (parcourt les cls),
values (parcourt les valeurs) ou items (parcourt les couples cl-valeur).
On peut capturer les paramtres nomms passs une fonction en utilisant cette syntaxe : def fonction_inconnue(**parametres_nommes : (les paramtres nomms se
retrouvent dans le dictionnaire parametres_nommes).

143

CHAPITRE 13. LES DICTIONNAIRES

144

Chapitre

14

Les fichiers
Difficult :

oursuivons notre tour dhorizon des principaux objets. Nous allons voir dans ce chapitre les fichiers, comment les ouvrir, les lire, crire dedans.

Nous finirons ce chapitre en voyant comment sauvegarder nos objets dans des fichiers, afin
de les utiliser dune session lautre de notre programme.

145

CHAPITRE 14. LES FICHIERS

Avant de commencer
Nous allons beaucoup travailler sur des rpertoires et des fichiers, autrement dit sur
votre disque. Donc je vais vous donner quelques informations gnrales avant de commencer pour que, malgr vos diffrents systmes et configurations, vous puissiez essayer
les instructions que je vais vous montrer.

Mais dabord, pourquoi lire ou crire dans des fichiers ?


Peut-tre que vous ne voyez pas trop lintrt de savoir lire et crire dans des fichiers,
hormis quelques applications de temps autre. Mais souvenez-vous que, quand vous
fermez votre programme, aucune de vos variables nest sauvegarde. Or, les fichiers
peuvent tre, justement, un excellent moyen de garder les valeurs de certains objets
pour pouvoir les rcuprer quand vous rouvrirez votre programme. Par exemple, un
petit jeu peut enregistrer les scores des joueurs.
Si, dans notre TP ZCasino, nous avions pu enregistrer la somme que nous avions en
poche au moment de quitter le casino, nous aurions pu rejouer sans repartir de zro.

Changer le rpertoire de travail courant


Si vous souhaitez travailler dans linterprteur Python, et je vous y encourage, vous
devrez changer le rpertoire de travail courant. En effet, au lancement de linterprteur,
le rpertoire de travail courant est celui dans lequel se trouve lexcutable de linterprteur. Sous Windows, cest C:\Python3X, le X tant diffrent en fonction de votre
version de Python. Dans tous les cas, je vous invite changer de rpertoire de travail
courant. Pour cela, vous devez utiliser une fonction du module os, qui sappelle chdir
(Change Directory).
1
2
3

>>> import os
>>> os . chdir (" C :/ tests python ")
>>>

Pour que cette instruction fonctionne, le rpertoire doit exister. Modifiez la chane
passe en paramtre de os.chdir en fonction du dossier dans lequel vous souhaitez
vous dplacer.
Je vous conseille, que vous soyez sous Windows ou non, dutiliser le symbole
/ pour dcrire un chemin.
Vous pouvez utiliser, en le doublant, lantislash \\ mais, si vous oubliez de le doubler,
vous aurez des erreurs. Je vous conseille donc dutiliser le slash /, cela fonctionne trs
bien mme sous Windows.
146

AVANT DE COMMENCER
Quand vous lancez un programme Python directement, par exemple en faisant un double-clic dessus, le rpertoire courant est celui do vous lancez le
programme. Si vous avez un fichier mon_programme.py contenu sur le disque
C:, le rpertoire de travail courant quand vous lancerez le programme sera
C:\.

Chemins relatifs et absolus


Pour dcrire larborescence dun systme, on a deux possibilits :
les chemins absolus ;
les chemins relatifs.

Le chemin absolu
Quand on dcrit une cible (un fichier ou un rpertoire) sous la forme dun chemin absolu,
on dcrit la suite des rpertoires menant au fichier. Sous Windows, on partira du nom
de volume (C:\, D:\. . .). Sous les systmes Unix, ce sera plus vraisemblablement depuis
/.
Par exemple, sous Windows, si on a un fichier nomm fic.txt, contenu dans un dossier
test, lui-mme prsent sur le disque C:, le chemin absolu menant notre fichier sera
C:\test\fic.txt.

Le chemin relatif
Quand on dcrit la position dun fichier grce un chemin relatif, cela veut dire que
lon tient compte du dossier dans lequel on se trouve actuellement. Ainsi, si on se trouve
dans le dossier C:\test et que lon souhaite accder au fichier fic.txt contenu dans
ce mme dossier, le chemin relatif menant ce fichier sera tout simplement fic.txt.
Maintenant, si on se trouve dans C:, notre chemin relatif sera test\fic.txt.
Quand on dcrit un chemin relatif, on utilise parfois le symbole .. qui dsigne le
rpertoire parent. Voici un nouvel exemple :
C:
test
rep1
fic1.txt
rep2
fic2.txt
fic3.txt
Cest dans notre dossier test que tout se passe. Nous avons deux sous-rpertoires
nomms rep1 et rep2. Dans rep1, nous avons un seul fichier : fic1.txt. Dans rep2,
nous avons deux fichiers : fic2.txt et fic3.txt.
147

CHAPITRE 14. LES FICHIERS


Si le rpertoire de travail courant est rep2 et que lon souhaite accder fic1.txt,
notre chemin relatif sera donc ..\rep1\fic1.txt.
Jutilise ici des anti-slash parce que lexemple darborescence est un modle
Windows et que ce sont les sparateurs utiliss pour dcrire une arborescence
Windows. Mais, dans votre code je vous conseille quand mme dutiliser un
slash (/).

Rsum
Les chemins absolus et relatifs sont donc deux moyens de dcrire le chemin menant
des fichiers ou rpertoires. Mais, si le rsultat est le mme, le moyen utilis nest pas
identique : quand on utilise un chemin absolu, on dcrit lintgralit du chemin menant
au fichier, peu importe lendroit o on se trouve. Un chemin absolu permet daccder
un endroit dans le disque quel que soit le rpertoire de travail courant. Linconvnient
de cette mthode, cest quon doit pralablement savoir o se trouvent, sur le disque,
les fichiers dont on a besoin.
Le chemin relatif dcrit la succession de rpertoires parcourir en prenant comme point
dorigine non pas la racine, ou le priphrique sur lequel est stocke la cible, mais le
rpertoire dans lequel on se trouve. Cela prsente certains avantages quand on code un
projet, on nest pas oblig de savoir o le projet est stock pour construire plusieurs
rpertoires. Mais ce nest pas forcment la meilleure solution en toutes circonstances.
Comme je lai dit, quand on lance linterprteur Python, on a bel et bien un rpertoire
de travail courant. Vous pouvez lafficher grce la fonction os.getcwd() 1 .
Cela devrait donc vous suffire. Pour les dmonstrations qui vont suivre, placez-vous,
laide de os.chdir, dans un rpertoire de test cr pour loccasion.

Lecture et criture dans un fichier


Nous allons commencer lire avant dcrire dans un fichier. Pour lexemple donc, je
vous invite crer un fichier dans le rpertoire de travail courant que vous avez choisi.
Je suis en manque flagrant dinspiration, je vais lappeler fichier.txt et je vais crire
dedans, laide dun diteur sans mise en forme (tel que le bloc-notes Windows) :
Cest le contenu du fichier. Spectaculaire non ?

Ouverture du fichier
Dabord, il nous faut ouvrir le fichier avec Python. On utilise pour ce faire la fonction
open, disponible sans avoir besoin de rien importer. Elle prend en paramtre :
le chemin (absolu ou relatif) menant au fichier ouvrir ;
1. CWD = Current Working Directory

148

LECTURE ET CRITURE DANS UN FICHIER


le mode douverture.
Le mode est donn sous la forme dune chane de caractres. Voici les principaux modes :
r : ouverture en lecture (Read).
w : ouverture en criture (Write). Le contenu du fichier est cras. Si le fichier
nexiste pas, il est cr.
a : ouverture en criture en mode ajout (Append). On crit la fin du fichier sans
craser lancien contenu du fichier. Si le fichier nexiste pas, il est cr.
On peut ajouter tous ces modes le signe b pour ouvrir le fichier en mode binaire.
Nous en verrons plus loin lutilit, cest un mode un peu particulier.
Ici nous souhaitons lire le fichier. Nous allons donc utiliser le mode r.
1
2
3
4
5
6

>>> mon_fichier = open (" fichier . txt " , " r ")


>>> mon_fichier
< _io . TextIOWrapper name = fichier . txt encoding = cp1252 >
>>> type ( mon_fichier )
< class _io . TextIOWrapper >
>>>

Lencodage prcis quand on affiche le fichier dans linterprteur peut tre trs diffrent
suivant votre systme. Ici, je suis dans linterprteur Python dans Windows et lencodage choisi est donc un encodage Windows propre la console. Ne soyez pas surpris
sil est diffrent chez vous.
La fonction open cre donc un fichier. Elle renvoie un objet de la classe TextIoWrapper.
Par la suite, nous allons utiliser des mthodes de cette classe pour interagir avec le
fichier.
Le type de lobjet doit vous surprendre quelque peu. Cela aurait trs bien pu tre un
type file aprs tout. En fait, open permet douvrir un fichier, mais TextIoWrapper
est utilis dans dautres circonstances, pour afficher du texte lcran par exemple.
Bon, cela ne nous concerne pas trop ici, je ne vais pas my attarder.

Fermer le fichier
Noubliez pas de fermer un fichier aprs lavoir ouvert. Si dautres applications, ou
dautres morceaux de votre propre code, souhaitent accder ce fichier, ils ne pourront
pas car le fichier sera dj ouvert. Cest surtout vrai en criture, mais prenez de bonnes
habitudes. La mthode utiliser est close :
1
2

>>> mon_fichier . close ()


>>>

149

CHAPITRE 14. LES FICHIERS

Lire lintgralit du fichier


Pour ce faire, on utilise la mthode read de la classe TextIoWrapper. Elle renvoie
lintgralit du fichier :
1
2
3
4
5
6

>>> mon_fichier = open (" fichier . txt " , " r ")


>>> contenu = mon_fichier . read ()
>>> print ( contenu )
C est le contenu du fichier . Spectaculaire non ?
>>> mon_fichier . close ()
>>>

Quoi de plus simple ? La mthode read renvoie tout le contenu du fichier, que lon
capture dans une chane de caractres. Notre fichier ne contient pas de saut de ligne
mais, si ctait le cas, vous auriez dans votre variable contenu les signes \n traduisant
un saut de ligne.
Maintenant que vous avez une chane, vous pouvez naturellement tout faire : la convertir, tout entire ou en partie, si cest ncessaire, split la chane pour parcourir chaque
ligne et les traiter. . . bref, tout est possible.

criture dans un fichier


Bien entendu, il nous faut ouvrir le fichier avant tout. Vous pouvez utiliser le mode
w ou le mode a. Le premier crase le contenu ventuel du fichier, alors que le second
ajoute ce que lon crit la fin du fichier. vous de voir en fonction de vos besoins.
Dans tous les cas, ces deux modes crent le fichier sil nexiste pas.

crire une chane


Pour crire dans un fichier, on utilise la mthode write en lui passant en paramtre la
chane crire dans le fichier. Elle renvoie le nombre de caractres qui ont t crits.
On nest naturellement pas oblig de rcuprer cette valeur, sauf si on en a besoin.
1
2
3
4
5

>>> mon_fichier = open (" fichier . txt " , " w ") # Argh j ai tout
cras !
>>> mon_fichier . write (" Premier test d criture dans un fichier
via Python ")
50
>>> mon_fichier . close ()
>>>

Vous pouvez vrifier que votre fichier contient bien le texte quon y a crit.
150

LECTURE ET CRITURE DANS UN FICHIER

crire dautres types de donnes


La mthode write naccepte en paramtre que des chanes de caractres. Si vous voulez
crire dans votre fichier des nombres, des scores par exemple, il vous faudra les convertir
en chane avant de les crire et les convertir en entier aprs les avoir lus.
Le module os contient beaucoup de fonctions intressantes pour crer et supprimer des
fichiers et des rpertoires. Je vous laisse regarder laide si vous tes intress.

Le mot-cl with
Ne dsesprez pas, il ne nous reste plus autant de mots-cls dcouvrir. . . mais
quelques-uns tout de mme. Et mme certains dont je ne parlerai pas. . .
On nest jamais labri dune erreur. Surtout quand on manipule des fichiers. Il peut
se produire des erreurs quand on lit, quand on crit. . . et si lon ny prend garde, le
fichier restera ouvert.
Comme je vous lai dit, cest plutt gnant et cela peut mme tre grave. Si votre
programme souhaite de nouveau utiliser ce fichier, il ne pourra pas forcment y accder,
puisquil a dj t ouvert.
Il existe un mot-cl qui permet dviter cette situation : with. Voici sa syntaxe :
1
2

with open ( mon_fichier , mode_ouverture ) as variable :


# Op rations sur le fichier

On trouve dans lordre :


Le mot-cl with, prlude au bloc dans lequel on va manipuler notre fichier. On peut
trouver with dans la manipulation dautres objets mais nous ne le verrons pas ici.
Notre objet. Ici, on appelle open qui va renvoyer un objet TextIOWrapper (notre
fichier).
Le mot-cl as que nous avons dj vu dans le mcanisme dimportation et dans les
exceptions. Il signifie toujours la mme chose : en tant que .
Notre variable qui contiendra notre objet. Si la variable nexiste pas, Python la cre.
Un exemple ?
1
2
3
4

>>> with open ( fichier . txt , r ) as mon_fichier :


...
texte = mon_fichier . read ()
...
>>>

Cela ne veut pas dire que le bloc dinstructions ne lvera aucune exception.

Cela signifie simplement que, si une exception se produit, le fichier sera tout de mme
ferm la fin du bloc.
151

CHAPITRE 14. LES FICHIERS


Le mot-cl with permet de crer un context manager (gestionnaire de contexte)
qui vrifie que le fichier est ouvert et ferm, mme si des erreurs se produisent pendant
le bloc. Vous verrez plus loin dautres objets utilisant le mme mcanisme.
Vous pouvez appeler mon_fichier.closed pour le vrifier. Si le fichier est ferm,
mon_fichier.closed vaudra True.
Il est inutile, par consquent, de fermer le fichier la fin du bloc with. Python va le
faire tout seul, quune exception soit leve ou non. Je vous encourage utiliser cette
syntaxe, elle est plus sre et plus facile comprendre.
Allez ! Direction le module pickle, dans lequel nous allons apprendre sauvegarder
nos objets dans des fichiers.

Enregistrer des objets dans des fichiers


Dans beaucoup de langages de haut niveau, on peut enregistrer ses objets dans un
fichier. Python ne fait pas exception. Grce au module pickle que nous allons dcouvrir, on peut enregistrer nimporte quel objet et le rcuprer par la suite, au prochain
lancement du programme, par exemple. En outre, le fichier rsultant pourra tre lu
depuis nimporte quel systme dexploitation ( condition, naturellement, que celui-ci
prenne en charge Python).

Enregistrer un objet dans un fichier


Il nous faut naturellement dabord importer le module pickle.
1
2

>>> import pickle


>>>

On va ensuite utiliser deux classes incluses dans ce module : la classe Pickler et la


classe Unpickler.
Cest la premire qui nous intresse dans cette section.
Pour crer notre objet Pickler, nous allons lappeler en passant en paramtre le fichier
dans lequel nous allons enregistrer notre objet.
1
2
3
4
5

>>> with open ( donnees , wb ) as fichier :


...
mon_pickler = pickle . Pickler ( fichier )
...
# enregistrement ...
...
>>>

Quand nous allons enregistrer nos objets, ce sera dans le fichier donnees. Je ne lui ai
pas donn dextension, vous pouvez le faire. Mais vitez de prciser une extension qui
est utilise par un programme.
152

ENREGISTRER DES OBJETS DANS DES FICHIERS


Notez le mode douverture : on ouvre le fichier donnees en mode dcriture binaire. Il
suffit de rajouter, derrire la lettre symbolisant le mode, la lettre b pour indiquer un
mode binaire.
Le fichier que Python va crire ne sera pas trs lisible si vous essayez de louvrir, mais
ce nest pas le but.
Bon. Maintenant que notre pickler est cr, nous allons enregistrer un ou plusieurs
objets dans notre fichier. L, cest vous de voir comment vous voulez vous organiser,
cela dpend aussi beaucoup du projet. Moi, jai pris lhabitude de nenregistrer quun
objet par fichier, mais il ny a aucune obligation.
On utilise la mthode dump du pickler pour enregistrer lobjet. Son emploi est des plus
simples :
1
2
3
4
5
6
7
8
9
10
11

>>> score = {
...
" joueur 1":
5,
...
" joueur 2":
35 ,
...
" joueur 3":
20 ,
...
" joueur 4":
2,
>>> }
>>> with open ( donnees , wb ) as fichier :
...
mon_pickler = pickle . Pickler ( fichier )
...
mon_pickler . dump ( score )
...
>>>

Aprs lexcution de ce code, vous avez dans votre dossier de test un fichier donnees
qui contient. . . eh bien, notre dictionnaire contenant les scores de nos quatre joueurs. Si
vous voulez enregistrer plusieurs objets, appelez de nouveau la mthode dump avec les
objets enregistrer. Ils seront ajouts dans le fichier dans lordre o vous les enregistrez.

Rcuprer nos objets enregistrs


Nous allons utiliser une autre classe dfinie dans notre module pickle. Cette fois, assez
logiquement, cest la classe Unpickler.
Commenons par crer notre objet. sa cration, on lui passe le fichier dans lequel
on va lire les objets. Puisquon va lire, on change de mode, on repasse en mode r, et
mme rb puisque le fichier est binaire.
1
2
3
4
5

>>> with open ( donnees , rb ) as fichier :


...
mon_depickler = pickle . Unpickler ( fichier )
...
# Lecture des objets contenus dans le fichier ...
...
>>>

Pour lire lobjet dans notre fichier, il faut appeler la mthode load de notre depickler.
Elle renvoie le premier objet qui a t lu (sil y en a plusieurs, il faut lappeler plusieurs
fois).
153

CHAPITRE 14. LES FICHIERS

1
2
3
4
5

>>> with open ( donnees , rb ) as fichier :


...
mon_depickler = pickle . Unpickler ( fichier )
...
score_recupere = mon_depickler . load ()
...
>>>

Et aprs cet appel, si le fichier a pu tre lu, dans votre variable score_recupere, vous
rcuprez votre dictionnaire contenant les scores. L, cest peut-tre peu spectaculaire
mais, quand vous utilisez ce module pour sauvegarder des objets devant tre conservs
alors que votre programme nest pas lanc, cest franchement trs pratique.

En rsum
On peut ouvrir un fichier en utilisant la fonction open prenant en paramtre le chemin
vers le fichier et le mode douverture.
On peut lire dans un fichier en utilisant la mthode read.
On peut crire dans un fichier en utilisant la mthode write.
Un fichier doit tre referm aprs usage en utilisant la mthode close.
Le module pickle est utilis pour enregistrer des objets Python dans des fichiers et
les recharger ensuite.

154

Chapitre

15

Porte des variables et rfrences


Difficult :
ans ce chapitre, je vais mattarder sur la porte des variables et sur les rfrences.
Je ne vais pas vous faire une visite guide de la mmoire de votre ordinateur (Python est assez haut niveau pour, justement, ne pas avoir descendre aussi bas), je
vais simplement souligner quelques cas intressants que vous pourriez rencontrer dans vos
programmes.

Ce chapitre nest pas indispensable, mais je ne lcris naturellement pas pour le plaisir :
vous pouvez trs bien continuer apprendre le Python sans connatre prcisment comment
Python joue avec les rfrences, mais il peut tre utile de le savoir.
Nhsitez pas relire ce chapitre si vous avez un peu de mal, les concepts prsents ne sont
pas vidents.

155

CHAPITRE 15. PORTE DES VARIABLES ET RFRENCES

La porte des variables


En Python, comme dans la plupart des langages, on trouve des rgles qui dfinissent
la porte des variables. La porte utilise dans ce sens cest quand et comment les
variables sont-elles accessibles ? . Quand vous dfinissez une fonction, quelles variables
sont utilisables dans son corps ? Uniquement les paramtres ? Est-ce quon peut crer
dans notre corps de fonction des variables utilisables en dehors ? Si vous ne vous tes
jamais pos ces questions, cest normal. Mais je vais tout de mme y rpondre car elles
ne sont pas dnues dintrt.

Dans nos fonctions, quelles variables sont accessibles ?


On ne change pas une quipe qui gagne : passons aux exemples ds prsent.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

>>> a = 5
>>> def print_a () :
...
""" Fonction charg e d afficher la variable a .
...
Cette variable a n est pas pass e en param tre de la
fonction .
...
On suppose qu elle a t cr e en dehors de la fonction
, on veut voir
...
si elle est accessible depuis le corps de la fonction
"""
...
...
print (" La variable a = {0}.". format ( a ) )
...
>>> print_a ()
La variable a = 5.
>>> a = 8
>>> print_a ()
La variable a = 8.
>>>

Surprise ! Ou peut-tre pas. . .


La variable a nest pas passe en paramtre de la fonction print_a. Et pourtant,
Python la trouve, tant quelle a t dfinie avant lappel de la fonction.
Cest l quinterviennent les diffrents espaces.
Lespace local
Dans votre fonction, quand vous faites rfrence une variable a, Python vrifie dans
lespace local de la fonction. Cet espace contient les paramtres qui sont passs la
fonction et les variables dfinies dans son corps. Python apprend ainsi que la variable a
nexiste pas dans lespace local de la fonction. Dans ce cas, il va regarder dans lespace
local dans lequel la fonction a t appele. Et l, il trouve bien la variable a et peut
donc lafficher.
156

LA PORTE DES VARIABLES


Dune faon gnrale, je vous conseille dviter dappeler des variables qui ne sont
pas dans lespace local, sauf si cest ncessaire. Ce nest pas trs clair la lecture ;
dans labsolu, prfrez travailler sur des variables globales, cela reste plus propre (nous
verrons cela plus bas). Pour linstant, on ne sintresse quaux mcanismes, on cherche
juste savoir quelles variables sont accessibles depuis le corps dune fonction et de
quelle faon.

La porte de nos variables


Voyons quelques cas concrets. Je vais les expliquer au fur et mesure, ne vous en faites
pas.
Quadvient-il des variables dfinies dans un corps de fonction ?
Voyons un nouvel exemple :
1
2
3

def set_var ( nouvelle_valeur ) :


""" Fonction nous permettant de tester la port e des
variables
d finies dans notre corps de fonction """

4
5
6
7
8
9
10
11

# On essaye d ' afficher la variable var , si elle existe


try :
print ( " Avant l ' affectation , notre variable var vaut { 0 }
. " . format ( var ) )
except NameError :
print ( " La variable var n ' existe pas encore . " )
var = nouvelle_valeur
print ( " Apr s l ' affectation , notre variable var vaut { 0 } . " .
format ( var ) )

Et maintenant, utilisons notre fonction :


1
2
3
4
5
6
7
8

>>> set_var (5)


La variable var n existe pas encore .
Apr s l affectation , notre variable var vaut 5.
>>> var
Traceback ( most recent call last ) :
File " < stdin >" , line 1 , in < module >
NameError : name var is not defined
>>>

Je sens que quelques explications simposent :


Lors de notre appel set_var, notre variable var na pu tre trouve par Python :
cest normal, nous ne lavons pas encore dfinie, ni dans notre corps de fonction,
ni dans le corps de notre programme. Python affecte la valeur 5 la variable var,
laffiche et sarrte.
157

CHAPITRE 15. PORTE DES VARIABLES ET RFRENCES


Au sortir de la fonction, on essaye dafficher la variable var. . . mais Python ne la
trouve pas ! En effet : elle a t dfinie dans le corps de la fonction (donc dans son
espace local) et, la fin de lexcution de la fonction, lespace est dtruit. . . donc la
variable var, dfinie dans le corps de la fonction, nexiste que dans ce corps et est
dtruite ensuite.
Python a une rgle daccs spcifique aux variables extrieures lespace local : on peut
les lire, mais pas les modifier. Cest pourquoi, dans notre fonction print_a, on arrivait
afficher une variable qui ntait pas comprise dans lespace local de la fonction. En revanche, on ne peut modifier la valeur dune variable extrieure lespace local, par affectation du moins. Si dans votre corps de fonction vous faites var = nouvelle_valeur,
vous nallez en aucun cas modifier une variable extrieure au corps.
En fait, quand Python trouve une instruction daffectation, comme par exemple var
= nouvelle_valeur, il va changer la valeur de la variable dans lespace local de la
fonction. Et rappelez-vous que cet espace local est dtruit aprs lappel la fonction.
Pour rsumer, et cest ce quil faut retenir, une fonction ne peut modifier, par affectation, la valeur dune variable extrieure son espace local.
Cela parat plutt stupide au premier abord. . . mais pas dimpatience. Je vais relativiser
cela assez rapidement.

Une fonction modifiant des objets


Jespre que vous vous en souvenez, en Python, tout est objet. Quand vous passez des
paramtres votre fonction, ce sont des objets qui sont transmis. Et pas les valeurs
des objets, mais bien les objets eux-mmes, ceci est trs important.
Bon. On ne peut affecter une nouvelle valeur un paramtre dans le corps de la
fonction. Je ne reviens pas l-dessus. En revanche, on pourrait essayer dappeler une
mthode de lobjet qui le modifie. . . Voyons cela :
1
2
3
4
5
6
7
8
9

>>> def ajouter ( liste , valeur_a_ajouter ) :


...
""" Cette fonction ins re la fin de la liste la valeur
que l on veut ajouter """
...
liste . append ( valeur_a_ajouter )
...
>>> ma_liste =[ a , e , i ]
>>> ajouter ( ma_liste , o )
>>> ma_liste
[ a , e , i , o ]
>>>

Cela marche ! On passe en paramtres notre objet de type list avec la valeur ajouter.
Et la fonction appelle la mthode append de lobjet. Cette fois, au sortir de la fonction,
notre objet a bel et bien t modifi.
158

LA PORTE DES VARIABLES


Je vois pas pourquoi. Tu as dit quune fonction ne pouvait pas affecter de
nouvelles valeurs aux paramtres ?
Absolument. Mais cest cela la petite subtilit dans lhistoire : on ne change pas du
tout la valeur du paramtre, on appelle juste une mthode de lobjet. Et cela change
tout. Si vous vous embrouillez, retenez que, dans le corps de fonction, si vous faites
parametre = nouvelle_valeur, le paramtre ne sera modifi que dans le corps de la
fonction. Alors que si vous faites parametre.methode_pour_modifier(...), lobjet
derrire le paramtre sera bel et bien modifi.
On peut aussi modifier les attributs dun objet, par exemple changer une case de la
liste ou dun dictionnaire : ces changements aussi seront effectifs au-del de lappel de
la fonction.

Et les rfrences, dans tout cela ?


Jai parl des rfrences, et vous ai promis dy consacrer une section ; cest maintenant
quon en parle !
Je vais schmatiser volontairement : les variables que nous utilisons depuis le dbut de
ce cours cachent en fait des rfrences vers des objets.
Concrtement, jai prsent les variables comme ceci : un nom identifiant pointant vers
une valeur. Par exemple, notre variable nomme a possde une valeur (disons 0).
En fait, une variable est un nom identifiant, pointant vers une rfrence dun objet.
La rfrence, cest un peu sa position en mmoire. Cela reste plus haut niveau que les
pointeurs en C par exemple, ce nest pas vraiment la mmoire de votre ordinateur. Et
on ne manipule pas ces rfrences directement.
Cela signifie que deux variables peuvent pointer sur le mme objet.
Bah. . . bien sr, rien nempche de faire deux variables avec la mme valeur.

Non non, je ne parle pas de valeurs ici mais dobjets. Voyons un exemple, vous allez
comprendre :
1
2
3
4
5
6
7
8

>>>
>>>
>>>
>>>
[1 ,
>>>
[1 ,
>>>

ma_liste1 = [1 , 2 , 3]
ma_liste2 = ma_liste1
ma_liste2 . append (4)
print ( ma_liste2 )
2 , 3 , 4]
print ( ma_liste1 )
2 , 3 , 4]

159

CHAPITRE 15. PORTE DES VARIABLES ET RFRENCES


Nous crons une liste dans la variable ma_liste1. la ligne 2, nous affectons ma_liste1
la variable ma_liste2. On pourrait croire que ma_liste2 est une copie de ma_liste1.
Toutefois, quand on ajoute 4 ma_liste2, ma_liste1 est aussi modifie.
On dit que ma_liste1 et ma_liste2 contiennent une rfrence vers le mme objet : si
on modifie lobjet depuis une des deux variables, le changement sera visible depuis les
deux variables.
Euh. . . jessaye de faire la mme chose avec des variables contenant des entiers
et cela ne marche pas.
Cest normal. Les entiers, les flottants, les chanes de caractres, nont aucune mthode
travaillant sur lobjet lui-mme. Les chanes de caractres, comme nous lavons vu, ne
modifient pas lobjet appelant mais renvoient un nouvel objet modifi. Et comme nous
venons de le voir, le processus daffectation nest pas du tout identique un appel de
mthode.
Et si je veux modifier une liste sans toucher lautre ?

Eh bien cest impossible, vu comment nous avons dfini nos listes. Les deux variables
pointent sur le mme objet par jeu de rfrences et donc, invitablement, si vous modifiez lobjet, vous allez voir le changement depuis les deux variables. Toutefois, il existe
un moyen pour crer un nouvel objet depuis un autre :
1
2
3
4
5
6
7
8

>>> ma_liste1 = [1 , 2 , 3]
>>> ma_liste2 = list ( ma_liste1 ) # Cela revient copier le
contenu de ma_liste1
>>> ma_liste2 . append (4)
>>> print ( ma_liste2 )
[1 , 2 , 3 , 4]
>>> print ( ma_liste1 )
[1 , 2 , 3]
>>>

la ligne 2, nous avons demand Python de crer un nouvel objet bas sur ma_liste1.
Du coup, les deux variables ne contiennent plus la mme rfrence : elles modifient des
objets diffrents. Vous pouvez utiliser la plupart des constructeurs (cest le nom quon
donne list pour crer une liste par exemple) dans ce but. Pour des dictionnaires,
utilisez le constructeur dict en lui passant en paramtre un dictionnaire dj construit
et vous aurez en retour un dictionnaire, semblable celui pass en paramtre, mais
seulement semblable par le contenu. En fait, il sagit dune copie de lobjet, ni plus ni
moins.
Pour approcher de plus prs les rfrences, vous avez la fonction id qui prend en
paramtre un objet. Elle renvoie la position de lobjet dans la mmoire Python sous la
160

LES VARIABLES GLOBALES


forme dun entier (plutt grand). Je vous invite faire quelques tests en passant divers
objets en paramtre cette fonction. Sachez au passage que is compare les ID des
objets de part et dautre et cest pour cette raison que je vous ais mis en garde quant
son utilisation.
1
2
3
4
5
6
7

>>> ma_liste1
>>> ma_liste2
>>> ma_liste1
True
>>> ma_liste1
False
>>>

= [1 , 2]
= [1 , 2]
== ma_liste2 # On compare le contenu des listes
is ma_liste2 # On compare leur r f rence

Je ne peux que vous encourager faire des tests avec diffrents objets. Un petit tour
du ct des variables globales ?

Les variables globales


Il existe un moyen de modifier, dans une fonction, des variables extrieures celle-ci.
On utilise pour cela des variables globales.
Cette distinction entre variables locales et variables globales se retrouve dans dautres
langages et on recommande souvent dviter de trop les utiliser. Elles peuvent avoir leur
utilit, toutefois, puisque le mcanisme existe. Dun point de vue strictement personnel,
tant que cest possible, je ne travaille quavec des variables locales (comme nous lavons
fait depuis le dbut de ce cours) mais il marrive de faire appel des variables globales
quand cest ncessaire ou bien plus pratique. Mais ne tombez pas dans lextrme non
plus, ni dans un sens ni dans lautre.

Le principe des variables globales


On ne peut faire plus simple. On dclare dans le corps de notre programme, donc en
dehors de tout corps de fonction, une variable, tout ce quil y a de plus normal. Dans le
corps dune fonction qui doit modifier cette variable (changer sa valeur par affectation),
on dclare Python que la variable qui doit tre utilise dans ce corps est globale.
Python va regarder dans les diffrents espaces : celui de la fonction, celui dans lequel
la fonction a t appele. . . ainsi de suite jusqu mettre la main sur notre variable. Sil
la trouve, il va nous donner le plein accs cette variable dans le corps de la fonction.
Cela signifie que nous pouvons y accder en lecture (comme cest le cas sans avoir
besoin de la dfinir comme variable globale) mais aussi en criture. Une fonction peut
donc ainsi changer la valeur dune variable directement.
Mais assez de thorie, voyons un exemple.
161

CHAPITRE 15. PORTE DES VARIABLES ET RFRENCES

Utiliser concrtement les variables globales


Pour dclarer Python, dans le corps dune fonction, que la variable qui sera utilise
doit tre considre comme globale, on utilise le mot-cl global. On le place gnralement aprs la dfinition de la fonction, juste en-dessous de la docstring, cela permet
de retrouver rapidement les variables globales sans parcourir tout le code (cest une
simple convention). On prcise derrire ce mot-cl le nom de la variable considrer
comme globale :
1
2
3
4
5
6
7
8
9
10
11
12

>>> i = 4 # Une variable , nomm e i , contenant un entier


>>> def inc_i () :
...
""" Fonction charg e d incr menter i de 1"""
...
global i # Python recherche i en dehors de l espace
local de la fonction
...
i += 1
...
>>> i
4
>>> inc_i ()
>>> i
5
>>>

Si vous ne prcisez pas Python que i doit tre considre comme globale, vous
ne pourrez pas modifier rellement sa valeur, comme nous lavons vu plus haut. En
prcisant global i, Python permet laccs en lecture et en criture cette variable,
ce qui signifie que vous pouvez changer sa valeur par affectation.
Jutilise ce mcanisme quand je travaille sur plusieurs classes et fonctions qui doivent
schanger des informations dtat par exemple. Il existe dautres moyens mais vous
connaissez celui-ci et, tant que vous matrisez bien votre code, il nest pas plus mauvais
quun autre.

En rsum
Les variables locales dfinies avant lappel dune fonction seront accessibles, depuis
le corps de la fonction, en lecture seule.
Une variable locale dfinie dans une fonction sera supprime aprs lexcution de
cette fonction.
On peut cependant appeler les attributs et mthodes dun objet pour le modifier
durablement.
Les variables globales se dfinissent laide du mot-cl global suivi du nom de la
variable pralablement cre.
Les variables globales peuvent tre modifies depuis le corps dune fonction ( utiliser
avec prudence).

162

Chapitre

16

TP : un bon vieux pendu


Difficult :

est le moment de mettre en pratique ce que vous avez appris. Vous naurez pas
besoin de tout, bien entendu, mais je vais essayer de vous faire travailler un maximum
de choses.

Nous allons donc faire un jeu de pendu plutt classique. Ce nest pas bien original mais on
va pimenter un peu lexercice, vous allez voir.

163

CHAPITRE 16. TP : UN BON VIEUX PENDU

Votre mission
Nous y voil. Je vais vous prciser un peu la mission, sans quoi on va avoir du mal
sentendre sur la correction.

Un jeu du pendu
Le premier point de la mission est de raliser un jeu du pendu. Je rappelle brivement
les rgles, au cas o : lordinateur choisit un mot au hasard dans une liste, un mot
de huit lettres maximum. Le joueur tente de trouver les lettres composant le mot.
chaque coup, il saisit une lettre. Si la lettre figure dans le mot, lordinateur affiche le
mot avec les lettres dj trouves. Celles qui ne le sont pas encore sont remplaces par
des toiles (*). Le joueur a 8 chances. Au del, il a perdu.
On va compliquer un peu les rgles en demandant au joueur de donner son nom, au
dbut de la partie. Cela permettra au programme denregistrer son score.
Le score du joueur sera simple calculer : on prend le score courant (0 si le joueur
na aucun score dj enregistr) et, chaque partie, on lui ajoute le nombre de coups
restants comme points de partie. Si, par exemple, il me reste trois coups au moment
o je trouve le mot, je gagne trois points.
Par la suite, vous pourrez vous amuser faire un dcompte plus pouss du score, pour
linstant cela suffira bien.

Le ct technique du problme
Le jeu du pendu en lui-mme, vous ne devriez avoir aucun problme le mettre en
place. Rappelez-vous que le joueur ne doit donner quune seule lettre la fois et que le
programme doit bien vrifier que cest le cas avant de continuer. Nous allons dcouper
notre programme en trois fichiers :
Le fichier donnees.py qui contiendra les variables ncessaires notre application (la
liste des mots, le nombre de chances autorises. . .).
Le fichier fonctions.py qui contiendra les fonctions utiles notre application. L, je
ne vous fais aucune liste claire, je vous conseille de bien y rflchir, avec une feuille et
un stylo si cela vous aide (Quelles sont les actions de mon programme ? Que puis-je
mettre dans des fonctions ?).
Enfin, notre fichier pendu.py qui contiendra notre jeu du pendu.

Grer les scores


Vous avez, jespre, une petite ide de comment faire cela. . . mais je vais quand mme
clarifier : on va enregistrer dans un fichier de donnes, que lon va appeler scores (sans
aucune extension) les scores du jeu. Ces scores seront sous la forme dun dictionnaire :
en cls, nous aurons les noms des joueurs et en valeurs les scores, sous la forme dentiers.
164

CORRECTION PROPOSE
Il faut grer les cas suivants :
Le fichier nexiste pas. L, on cre un dictionnaire vide, aucun score na t trouv.
Le joueur nest pas dans le dictionnaire. Dans ce cas, on lajoute avec un score de 0.

vous de jouer
Vous avez lessentiel. Peut-tre pas tout ce dont vous avez besoin, cela dpend de
comment vous vous organisez, mais le but est aussi de chercher ! Encore une fois, cest
un exercice pratique, ne sautez pas la correction tout de suite, cela ne vous apprendra
pas grand chose.
Bonne chance !

Correction propose
Voici la correction que je vous propose. Jespre que vous tes arrivs un rsultat
satisfaisant, mme si vous navez pas forcment russi tout faire. Si votre jeu marche,
cest parfait !


Tlcharger les fichiers
B
Code web : 934163


Voici le code des trois fichiers.

donnees.py
1
2

""" Ce fichier d finit quelques donn es , sous la forme de


variables ,
utiles au programme pendu """

3
4
5

# Nombre de coups par partie


nb_coups = 8

6
7
8

# Nom du fichier stockant les scores


no m_ fi chi er _s cores = " scores "

9
10
11
12
13
14
15
16
17
18
19
20

# Liste des mots du pendu


liste_mots = [
" armoire " ,
" boucle " ,
" buisson " ,
" bureau " ,
" chaise " ,
" carton " ,
" couteau " ,
" fichier " ,
" garage " ,

165

CHAPITRE 16. TP : UN BON VIEUX PENDU


21
22
23
24
25
26
27
28
29
30
31
32

" glace " ,


" journal " ,
" kiwi " ,
" lampe " ,
" liste " ,
" montagne " ,
" remise " ,
" sandale " ,
" taxi " ,
" vampire " ,
" volant " ,

fonctions.py
1

""" Ce fichier d finit des fonctions utiles pour le programme


pendu .

2
3

On utilise les donn es du programme contenues dans donnees . py


"""

4
5
6
7

import os
import pickle
from random import choice

8
9

from donnees import *

10
11

# Gestion des scores

12
13
14
15
16
17

def recup_scores () :
""" Cette fonction r cup re les scores enregistr s si le
fichier existe .
Dans tous les cas , on renvoie un dictionnaire ,
soit l ' objet d pickl ,
soit un dictionnaire vide .

18

On s ' appuie sur nom_fichier_scores d fini dans donnees . py


"""

19
20

if os . path . exists ( nom_fichier_scores ) : # Le fichier existe


# On le r cup re
fichier_scores = open ( nom_fichier_scores , " rb " )
mon_depickler = pickle . Unpickler ( fichier_scores )
scores = mon_depickler . load ()
fichier_scores . close ()
else : # Le fichier n ' existe pas
scores = { }
return scores

21
22
23
24
25
26
27
28
29
30
31

def e nr eg istrer_scores ( scores ) :

166

CORRECTION PROPOSE
32
33
34

""" Cette fonction se charge d ' enregistrer les scores dans


le fichier
no m_ fi chi er_scores . Elle re oit en param tre le
dictionnaire des scores
enregistrer """

35
36
37
38
39

fichier_scores = open ( nom_fichier_scores , " wb " ) # On crase


les anciens scores
mon_pickler = pickle . Pickler ( fichier_scores )
mon_pickler . dump ( scores )
fichier_scores . close ()

40
41

# Fonctions g rant les l ments saisis par l ' utilisateur

42
43
44
45
46

def r e c u p _ n o m _uti lisate ur () :


""" Fonction charg e de r cup rer le nom de l ' utilisateur .
Le nom de l ' utilisateur doit tre compos de 4 caract res
minimum ,
chiffres et lettres exclusivement .

47
48
49

Si ce nom n ' est pas valide , on appelle r cursivement la


fonction
pour en obtenir un nouveau """

50
51
52
53
54
55
56
57
58
59

nom_utilisateur = input ( " Tapez votre nom : " )


# On met la premi re lettre en majuscule et les autres en
minuscules
nom_utilisateur = nom_utilisateur . capitalize ()
if not nom_utilisateur . isalnum () or len ( nom_utilisateur ) <4 :
print ( " Ce nom est invalide . " )
# On appelle de nouveau la fonction pour avoir un autre
nom
return recu p_nom_ utilis ateur ()
else :
return nom_utilisateur

60
61
62
63
64

def recup_lettre () :
""" Cette fonction r cup re une lettre saisie par
l ' utilisateur . Si la cha ne r cup r e n ' est pas une lettre ,
on appelle r cursivement la fonction jusqu ' obtenir une
lettre """

65
66
67
68
69
70
71
72

lettre = input ( " Tapez une lettre : " )


lettre = lettre . lower ()
if len ( lettre ) >1 or not lettre . isalpha () :
print ( " Vous n ' avez pas saisi une lettre valide . " )
return recup_lettre ()
else :
return lettre

73

167

CHAPITRE 16. TP : UN BON VIEUX PENDU


74

# Fonctions du jeu de pendu

75
76
77
78

def choisir_mot () :
""" Cette fonction renvoie le mot choisi dans la liste des
mots
liste_mots .

79

On utilise la fonction choice du module random ( voir l ' aide


) . """

80
81

return choice ( liste_mots )

82
83
84
85
86
87

def recup_mot_masque ( mot_complet , lettres_trouvees ) :


""" Cette fonction renvoie un mot masqu tout ou en partie ,
en fonction :
- du mot d ' origine ( type str )
- des lettres d j trouv es ( type list )

88

On renvoie le mot d ' origine avec des * rempla ant les


lettres que l ' on
n 'a pas encore trouv es . """

89
90
91

mot_masque = " "


for lettre in mot_complet :
if lettre in lettres_trouvees :
mot_masque += lettre
else :
mot_masque += " * "
return mot_masque

92
93
94
95
96
97
98

pendu.py
1

""" Ce fichier contient le jeu du pendu .

2
3
4
5

Il s ' appuie sur les fichiers :


- donnees . py
- fonctions . py """

6
7
8
9

from donnees import *


from fonctions import *

10
11
12

# On r cup re les scores de la partie


scores = recup_scores ()

13
14
15

# On r cup re un nom d ' utilisateur


utilisateur = rec up_nom _util isateu r ()

16
17
18

# Si l ' utilisateur n 'a pas encore de score , on l ' ajoute


if utilisateur not in scores . keys () :

168

CORRECTION PROPOSE
19

scores [ utilisateur ] = 0 # 0 point pour commencer

20
21
22

# Notre variable pour savoir quand arr ter la partie


continuer_partie = 'o '

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

while continuer_partie != 'n ':


print ( " Joueur { 0 } : { 1 } point ( s ) " . format ( utilisateur , scores
[ utilisateur ]) )
mot_a_trouver = choisir_mot ()
lettres_trouvees = []
mot_trouve = recup_mot_masque ( mot_a_trouver ,
lettres_trouvees )
nb_chances = nb_coups
while mot_a_trouver != mot_trouve and nb_chances > 0 :
print ( " Mot trouver { 0 } ( encore { 1 } chances ) " . format (
mot_trouve , nb_chances ) )
lettre = recup_lettre ()
if lettre in lettres_trouvees : # La lettre a d j t
choisie
print ( " Vous avez d j choisi cette lettre . " )
elif lettre in mot_a_trouver : # La lettre est dans le
mot trouver
lettres_trouvees . append ( lettre )
print ( " Bien jou . " )
else :
nb_chances -= 1
print ( " ... non , cette lettre ne se trouve pas dans
le mot ... " )
mot_trouve = recup_mot_masque ( mot_a_trouver ,
lettres_trouvees )

42
43
44
45
46
47

# A -t - on trouv le mot ou nos chances sont - elles puis es ?


if mot_a_trouver == mot_trouve :
print ( " F licitations ! Vous avez trouv le mot { 0 } . " . format
( mot_a_trouver ) )
else :
print ( " PENDU !!! Vous avez perdu . " )

48
49
50

# On met jour le score de l ' utilisateur


scores [ utilisateur ] += nb_chances

51
52
53

continuer_partie = input ( " Souhaitez - vous continuer la


partie ( O / N ) ? " )
continuer_partie = continuer_partie . lower ()

54
55
56

# La partie est finie , on enregistre les scores


en re gi str er _s cores ( scores )

57
58
59

# On affiche les scores de l ' utilisateur


print ( " Vous finissez la partie avec { 0 } points . " . format ( scores [

169

CHAPITRE 16. TP : UN BON VIEUX PENDU


utilisateur ]) )

Rsum
Dans lensemble, je ne pense pas que le code soit trs dlicat comprendre. Vous pouvez
vous rendre compte quel point le code du jeu est facile lire grce nos fonctions.
On dlgue une partie de lapplication nos fonctions qui sassurent que les choses sont
bien faites . Si un bug survient, il est plus facile de modifier une fonction que tout
un code sans aucune structure.
Par cet exemple, jespre que vous prendrez bien lhabitude de documenter un maximum vos fichiers et fonctions. Cest rellement un bon rflexe avoir.
Noubliez pas la spcification de lencodage en tte de chaque fichier, ni la
mise en pause du programme sous Windows.

170

Troisime partie

La Programmation Oriente
Objet ct dveloppeur

171

Chapitre

17

Premire approche des classes


Difficult :

ans ce chapitre, sans plus attendre, nous allons crer nos premires classes, nos
premiers attributs et nos premires mthodes. Nous allons aussi essayer de comprendre
les mcanismes de la programmation oriente objet en Python.

Au-del du mcanisme, lorient objet est une vritable philosophie et Python est assez
diffrent des autres langages, en termes de philosophie justement. Restez concentrs, ce
langage na pas fini de vous tonner !

173

CHAPITRE 17. PREMIRE APPROCHE DES CLASSES

Les classes, tout un monde


Dans la partie prcdente, javais brivement dcrit les objets comme des variables
pouvant contenir elles-mmes des fonctions et variables. Nous sommes alls plus loin
tout au long de la seconde partie, pour dcouvrir que nos fonctions contenues dans
nos objets sont appeles des mthodes. En vrit, je me suis cantonn une dfinition
pratique des objets, alors que derrire la POO (Programmation Oriente Objet) se
cache une vritable philosophie.

Pourquoi utiliser des objets ?


Les premiers langages de programmation nincluaient pas lorient objet. Le langage
C, pour ne citer que lui, nutilise pas ce concept et il aura fallu attendre le C++ pour
utiliser la puissance de lorient objet dans une syntaxe proche de celle du C.
Java, un langage apparu peu prs en mme temps que Python, dfinit une philosophie
assez diffrente de celle du C++ : contrairement ce dernier, le Java exige que tout
soit rang dans des classes. Mme lapplication standard Hello World est contenue
dans une classe.
En Python, la libert est plus grande. Aprs tout, vous avez pu passer une partie de
ce cours sans connatre la faade objet de Python. Et pourtant, le langage Python est
totalement orient objet : en Python, tout est objet, vous navez pas oubli ? Quand
vous croyez utiliser une simple variable, un module, une fonction. . ., ce sont des objets
qui se cachent derrire.
Loin de moi lide de faire un comparatif entre diffrents langages. Ce sur quoi je
souhaite attirer votre attention, cest que plusieurs langages intgrent lorient objet,
chacun avec une philosophie distincte. Autrement dit, si vous avez appris lorient objet
dans un autre langage, tel que le C++ ou le Java, ne tenez pas pour acquis que vous
allez retrouver les mme mcanismes et surtout, la mme philosophie. Gardez autant
que possible lesprit dgag de tout prjug sur la philosophie objet de Python.
Pour linstant, nous navons donc vu quun aspect technique de lobjet. Jirais jusqu
dire que ce quon a vu jusquici, ce ntait quune faon un peu plus esthtique
de coder : il est plus simple et plus comprhensible dcrire ma_liste.append(5) que
append_to_list(ma_liste, 5). Mais derrire la POO, il ny a pas quun souci esthtique, loin de l.

Choix du modle
Bon, comme vous vous en souvenez srement (du moins, je lespre), une classe est un
peu un modle suivant lequel on va crer des objets. Cest dans la classe que nous allons
dfinir nos mthodes et attributs, les attributs tant des variables contenues dans notre
objet.
Mais quallons-nous modliser ? Lorient objet est plus quutile ds lors que lon sen
sert pour modliser, reprsenter des donnes un peu plus complexes quun simple
174

NOS PREMIERS ATTRIBUTS


nombre, ou quune chane de caractres. Bien sr, il existe des classes que Python
dfinit pour nous : les nombres, les chanes et les listes en font partie. Mais on serait
bien limit si on ne pouvait faire ses propres classes.
Pour linstant, nous allons modliser. . . une personne. Cest le premier exemple qui me
soit venu lesprit, nous verrons bien dautres exemples avant la fin de la partie.

Convention de nommage
Loin de moi lide de compliquer lexercice mais si on se rfre la PEP 8 1 de Python
, il est prfrable dutiliser pour des noms de classes la convention dite Camel Case.


PEP 8 de Python
B
Code web : 484505


Cette convention nutilise pas le signe soulign _ pour sparer les mots. Le principe
consiste mettre en majuscule chaque lettre dbutant un mot, par exemple : MaClasse.
Cest donc cette convention que je vais utiliser pour les noms de classes. Libre vous
den changer, encore une fois rien nest impos.
Pour dfinir une nouvelle classe, on utilise le mot-cl class.
Sa syntaxe est assez intuitive : class NomDeLaClasse:.
Nexcutez pas encore ce code, nous ne savons pas comment dfinir nos attributs et
nos mthodes.
Petit exercice de modlisation : que va-t-on trouver dans les caractristiques dune
personne ? Beaucoup de choses, vous en conviendrez. On ne va en retenir que quelquesunes : le nom, le prnom, lge, le lieu de rsidence. . . allez, cela suffira.
Cela nous fait donc quatre attributs. Ce sont les variables internes notre objet, qui
vont le caractriser. Une personne telle que nous la modlisons sera caractrise par
son nom, son prnom, son ge et son lieu de rsidence.
Pour dfinir les attributs de notre objet, il faut dfinir un constructeur dans notre
classe. Voyons cela de plus prs.

Nos premiers attributs


Nous avons dfini les attributs qui allaient caractriser notre objet de classe Personne.
Maintenant, il faut dfinir dans notre classe une mthode spciale, appele un constructeur, qui est appele invariablement quand on souhaite crer un objet depuis notre
classe.
Concrtement, un constructeur est une mthode de notre objet se chargeant de crer
nos attributs. En vrit, cest mme la mthode qui sera appele quand on voudra crer
notre objet.
1. Les PEP sont les Python Enhancement Proposals , cest dire les propositions damlioration
de Python.

175

CHAPITRE 17. PREMIRE APPROCHE DES CLASSES


Voyons le code, ce sera plus parlant :
class Personne : # D finition de notre classe Personne
""" Classe d finissant une personne caract ris e par :
- son nom
- son pr nom
- son ge
- son lieu de r sidence """

1
2
3
4
5
6
7
8

def __init__ ( self ) : # Notre m thode constructeur


""" Pour l ' instant , on ne va d finir qu ' un seul attribut
"""
self . nom = " Dupont "

9
10
11

Voyons en dtail :
Dabord, la dfinition de la classe. Elle est constitue du mot-cl class, du nom de
la classe et des deux points rituels : .
Une docstring commentant la classe. Encore une fois, cest une excellente habitude
prendre et je vous encourage le faire systmatiquement. Ce pourra tre plus
quutile quand vous vous lancerez dans de grands projets, notamment plusieurs.
La dfinition de notre constructeur. Comme vous le voyez, il sagit dune dfinition
presque classique dune fonction. Elle a pour nom __init__, cest invariable : en
Python, tous les constructeurs sappellent ainsi. Nous verrons plus tard que les noms
de mthodes entours de part et dautre de deux signes souligns (__nommethode__)
sont des mthodes spciales. Notez que, dans notre dfinition de mthode, nous
passons un premier paramtre nomm self.
Une nouvelle docstring. Je ne complique pas inutilement, je prcise donc quon va
simplement dfinir un seul attribut pour linstant dans notre constructeur.
Dans notre constructeur, nous trouvons linstanciation de notre attribut nom. On
cre une variable self.nom et on lui donne comme valeur Dupont. Je vais dtailler
un peu plus bas ce qui se passe ici.
Avant tout, pour voir le rsultat en action, essayons de crer un objet issu de notre
classe :
1
2
3
4
5
6

>>> bernard = Personne ()


>>> bernard
< __main__ . Personne object at 0 x00B42570 >
>>> bernard . nom
Dupont
>>>

Quand on demande linterprteur dafficher directement notre objet bernard, il nous


sort quelque chose dun peu imbuvable. . . Bon, lessentiel est la mention prcisant la
classe dont lobjet est issu. On peut donc vrifier que cest bien notre classe Personne
dont est issu notre objet. On essaye ensuite dafficher lattribut nom de notre objet
bernard et on obtient Dupont (la valeur dfinie dans notre constructeur). Notez
quon utilise le point (.), encore et toujours utilis pour une relation dappartenance
176

NOS PREMIERS ATTRIBUTS


(nom est un attribut de lobjet bernard). Encore un peu dexplications :

Quand on cre notre objet. . .


Quand on tape Personne(), on appelle le constructeur de notre classe Personne, dune
faon quelque peu indirecte que je ne dtaillerai pas ici. Celui-ci prend en paramtre
une variable un peu mystrieuse : self. En fait, il sagit tout btement de notre objet
en train de se crer. On crit dans cet objet lattribut nom le plus simplement du
monde : self.nom = "Dupont". la fin de lappel au constructeur, Python renvoie
notre objet self modifi, avec notre attribut. On va rceptionner le tout dans notre
variable bernard.
Si ce nest pas trs clair, pas de panique ! Vous pouvez vous contenter de vous familiariser avec la syntaxe du constructeur Python, qui sera souvent la mme, et laisser
laspect un peu thorique de ct, pour plus tard. Nous aurons loccasion dy revenir
avant la fin du chapitre.

toffons un peu notre constructeur


Bon, on avait dit quatre attributs, on nen a fait quun. Et puis notre constructeur pourrait viter de donner les mmes valeurs par dfaut chaque fois,
tout de mme !
Cest juste. Dans un premier temps, on va se contenter de dfinir les autres attributs,
le prnom, lge, le lieu de rsidence. Essayez de le faire, normalement vous ne devriez
prouver aucune difficult.
Voici le code, au cas o :
1
2
3
4
5
6

class Personne :
""" Classe d finissant une personne caract ris e par :
- son nom
- son pr nom
- son ge
- son lieu de r sidence """

7
8
9
10
11

def __init__ ( self ) : # Notre m thode constructeur


""" Constructeur de notre classe . Chaque attribut va
tre instanci
avec une valeur par d faut ... original """

12
13
14
15
16
17

self . nom = " Dupont "


self . prenom = " Jean " # Quelle originalit
self . age = 33 # Cela n ' engage rien
self . lieu_residence = " Paris "

177

CHAPITRE 17. PREMIRE APPROCHE DES CLASSES


Cela vous parat vident ? Encore un petit code dexemple :
1
2
3
4
5
6
7
8
9
10
11
12
13
14

>>> jean = Personne ()


>>> jean . nom
Dupont
>>> jean . prenom
Jean
>>> jean . age
33
>>> jean . lieu_residence
Paris
>>> # Jean d m nage...
... jean . lieu_residence = " Berlin "
>>> jean . lieu_residence
Berlin
>>>

Je sens un courant dair. . . les habitus de lobjet, une minute.


Cet exemple me parat assez clair, sur le principe de dfinition des attributs, accs aux
attributs dun objet cr, modification des attributs dun objet.
Une toute petite explication en ce qui concerne la ligne 11 : dans beaucoup de cours, on
dconseille de modifier un attribut dinstance (un attribut dun objet) comme on vient
de le faire, en faisant simplement objet.attribut = valeur. Si vous venez dun autre
langage, vous pourrez avoir entendu parler des accesseurs et mutateurs. Ces concepts
sont repris dans certains cours Python, mais ils nont pas prcisment lieu dtre dans
ce langage. Tout cela, je le dtaillerai dans le prochain chapitre. Pour linstant, il vous
suffit de savoir que, quand vous voulez modifier un attribut dun objet, vous crivez
objet.attribut = nouvelle_valeur. Nous verrons les cas particuliers plus loin.
Bon. Il nous reste encore faire un constructeur un peu plus intelligent. Pour linstant,
quel que soit lobjet cr, il possde les mmes nom, prnom, ge et lieu de rsidence.
On peut les modifier par la suite, bien entendu, mais on peut aussi faire en sorte
que le constructeur prenne plusieurs paramtres, disons. . . le nom et le prnom, pour
commencer.
1
2
3
4
5
6

class Personne :
""" Classe d finissant une personne caract ris e par :
- son nom
- son pr nom
- son ge
- son lieu de r sidence """

7
8
9
10
11
12
13
14

178

def __init__ ( self , nom , prenom ) :


""" Constructeur de notre classe """
self . nom = nom
self . prenom = prenom
self . age = 33
self . lieu_residence = " Paris "

NOS PREMIERS ATTRIBUTS


Et en images :
1
2
3
4
5
6
7
8

>>> bernard = Personne (" Micado " , " Bernard ")


>>> bernard . nom
Micado
>>> bernard . prenom
Bernard
>>> bernard . age
33
>>>

Noubliez pas que le premier paramtre doit tre self. En dehors de cela, un constructeur est une fonction plutt classique : vous pouvez dfinir des paramtres, par dfaut
ou non, nomms ou non. Quand vous voudrez crer votre objet, vous appellerez le
nom de la classe en passant entre parenthses les paramtres utiliser. Faites quelques
tests, avec plus ou moins de paramtres, je pense que vous saisirez trs rapidement le
principe.

Attributs de classe
Dans les exemples que nous avons vus jusqu prsent, nos attributs sont contenus dans
notre objet. Ils sont propres lobjet : si vous crez plusieurs objets, les attributs nom,
prenom,. . . de chacun ne seront pas forcment identiques dun objet lautre. Mais on
peut aussi dfinir des attributs dans notre classe. Voyons un exemple :
1
2
3

class Compteur :
""" Cette classe poss de un attribut de classe qui s ' incr
mente chaque
fois que l ' on cr e un objet de ce type """

4
5

objets_crees = 0 # Le compteur vaut 0 au d part


def __init__ ( self ) :
""" chaque fois qu ' on cr e un objet , on incr mente le
compteur """
Compteur . objets_crees += 1

6
7
8
9

On dfinit notre attribut de classe directement dans le corps de la classe, sous la


dfinition et la docstring, avant la dfinition du constructeur. Quand on veut lappeler
dans le constructeur, on prfixe le nom de lattribut de classe par le nom de la classe.
Et on y accde de cette faon galement, en dehors de la classe. Voyez plutt :
1
2
3
4
5
6
7

>>>
0
>>>
>>>
1
>>>
>>>

Compteur . objets_crees
a = Compteur () # On cr e un premier objet
Compteur . objets_crees
b = Compteur ()
Compteur . objets_crees

179

CHAPITRE 17. PREMIRE APPROCHE DES CLASSES


8
9

2
>>>

chaque fois quon cre un objet de type Compteur, lattribut de classe objets_crees
sincrmente de 1. Cela peut tre utile davoir des attributs de classe, quand tous nos
objets doivent avoir certaines donnes identiques. Nous aurons loccasion den reparler
par la suite.

Les mthodes, la recette


Les attributs sont des variables propres notre objet, qui servent le caractriser. Les
mthodes sont plutt des actions, comme nous lavons vu dans la partie prcdente,
agissant sur lobjet. Par exemple, la mthode append de la classe list permet dajouter
un lment dans lobjet list manipul.
Pour crer nos premires mthodes, nous allons modliser. . . un tableau. Un tableau
noir, oui cest trs bien.
Notre tableau va possder une surface (un attribut) sur laquelle on pourra crire,
que lon pourra lire et effacer. Pour crer notre classe TableauNoir et notre attribut
surface, vous ne devriez pas avoir de problme :
1
2
3
4

class TableauNoir :
""" Classe d finissant une surface sur laquelle on peut
crire ,
que l ' on peut lire et effacer , par jeu de m thodes . L '
attribut modifi
est ' surface ' """

5
6
7
8
9

def __init__ ( self ) :


""" Par d faut , notre surface est vide """
self . surface = " "

Nous avons dj cr une mthode, aussi vous ne devriez pas tre trop surpris par la
syntaxe que nous allons voir. Notre constructeur est en effet une mthode, elle en garde
la syntaxe. Nous allons donc crire notre mthode ecrire pour commencer.
1
2
3
4

class TableauNoir :
""" Classe d finissant une surface sur laquelle on peut
crire ,
que l ' on peut lire et effacer , par jeu de m thodes . L '
attribut modifi
est ' surface ' """

5
6
7
8
9

180

def __init__ ( self ) :


""" Par d faut , notre surface est vide """
self . surface = " "

LES MTHODES, LA RECETTE


10
11
12
13

def ecrire ( self , message_a_ecrire ) :


""" M thode permettant d ' crire sur la surface du
tableau .
Si la surface n ' est pas vide , on saute une ligne avant
de rajouter
le message crire """

14
15
16
17
18

if self . surface != " " :


self . surface += " \ n "
self . surface += message_a_ecrire

Passons aux tests :


1
2
3
4
5
6
7
8
9
10
11
12
13

>>> tab = TableauNoir ()


>>> tab . surface

>>> tab . ecrire (" Coooool ! Ce sont les vacances !")


>>> tab . surface
" Coooool ! Ce sont les vacances !"
>>> tab . ecrire (" Joyeux No l !")
>>> tab . surface
" Coooool ! Ce sont les vacances !\ nJoyeux No l !"
>>> print ( tab . surface )
Coooool ! Ce sont les vacances !
Joyeux No l !
>>>

Notre mthode ecrire se charge dcrire sur notre surface, en rajoutant un saut de
ligne pour sparer chaque message.
On retrouve ici notre paramtre self. Il est temps de voir un peu plus en dtail quoi
il sert.

Le paramtre self
Dans nos mthodes dinstance, quon appelle galement des mthodes dobjet, on
trouve dans la dfinition ce paramtre self. Lheure est venue de comprendre ce quil
signifie.
Une chose qui a son importance : quand vous crez un nouvel objet, ici un tableau
noir, les attributs de lobjet sont propres lobjet cr. Cest logique : si vous crez
plusieurs tableaux noirs, ils ne vont pas tous avoir la mme surface. Donc les attributs
sont contenus dans lobjet.
En revanche, les mthodes sont contenues dans la classe qui dfinit notre objet. Cest
trs important. Quand vous tapez tab.ecrire(...), Python va chercher la mthode
ecrire non pas dans lobjet tab, mais dans la classe TableauNoir.
1

>>> tab . ecrire

181

CHAPITRE 17. PREMIRE APPROCHE DES CLASSES


2
3
4
5
6
7
8
9
10
11
12
13
14

< bound method TableauNoir . ecrire of < __main__ . TableauNoir


object at 0 x00B3F3F0 > >
>>> TableauNoir . ecrire
< function ecrire at 0 x00BA5810 >
>>> help ( TableauNoir . ecrire )
Help on function ecrire in module __main__ :
ecrire ( self , message_a_ecrire )
M thode permettant d crire sur la surface du tableau .
Si la surface n est pas vide , on saute une ligne avant de
rajouter
le message crire .
>>> TableauNoir . ecrire ( tab , " essai ")
>>> tab . surface
essai
>>>

Comme vous le voyez, quand vous tapez tab.ecrire(...), cela revient au mme que
si vous crivez TableauNoir.ecrire(tab, ...). Votre paramtre self, cest lobjet
qui appelle la mthode. Cest pour cette raison que vous modifiez la surface de lobjet
en appelant self.surface.
Pour rsumer, quand vous devez travailler dans une mthode de lobjet sur lobjet
lui-mme, vous allez passer par self.
Le nom self est une trs forte convention de nommage. Je vous dconseille de changer
ce nom. Certains programmeurs, qui trouvent qucrire self chaque fois est excessivement long, labrgent en une unique lettre s. vitez ce raccourci. De manire gnrale,
vitez de changer le nom. Une mthode dinstance travaille avec le paramtre self.
Nest-ce pas effectivement plutt long de devoir toujours travailler avec self
chaque fois quon souhaite faire appel lobjet ?
Cela peut le sembler, oui. Cest dailleurs lun des reproches quon fait au langage
Python. Certains langages travaillent implicitement sur les attributs et mthodes dun
objet sans avoir besoin de les appeler spcifiquement. Mais cest moins clair et cela peut
susciter la confusion. En Python, ds quon voit self, on sait que cest un attribut ou
une mthode interne lobjet qui va tre appel.
Bon, voyons nos autres mthodes. Nous devons encore coder lire qui va se charger
dafficher notre surface et effacer qui va effacer le contenu de notre surface. Si vous
avez compris ce que je viens dexpliquer, vous devriez crire ces mthodes sans aucun
problme, elles sont trs simples. Sinon, nhsitez pas relire, jusqu ce que le dclic
se fasse.
1
2
3

182

class TableauNoir :
""" Classe d finissant une surface sur laquelle on peut
crire ,
que l ' on peut lire et effacer , par jeu de m thodes . L '
attribut modifi

LES MTHODES, LA RECETTE


4

est ' surface ' """

5
6
7
8
9
10
11
12
13

def __init__ ( self ) :


""" Par d faut , notre surface est vide """
self . surface = " "
def ecrire ( self , message_a_ecrire ) :
""" M thode permettant d ' crire sur la surface du
tableau .
Si la surface n ' est pas vide , on saute une ligne avant
de rajouter
le message crire """

14
15
16
17
18
19
20
21

if self . surface != " " :


self . surface += " \ n "
self . surface += message_a_ecrire
def lire ( self ) :
""" Cette m thode se charge d ' afficher , gr ce print ,
la surface du tableau """

22
23
24
25
26
27

print ( self . surface )


def effacer ( self ) :
""" Cette m thode permet d ' effacer la surface du tableau
"""
self . surface = " "

Et encore une fois, le code de test :


1
2
3
4
5
6
7
8
9
10

>>> tab = TableauNoir ()


>>> tab . lire ()
>>> tab . ecrire (" Salut tout le monde .")
>>> tab . ecrire (" La forme ?")
>>> tab . lire ()
Salut tout le monde .
La forme ?
>>> tab . effacer ()
>>> tab . lire ()
>>>

Et voil ! Avec nos mthodes bien documentes, un petit coup de help(TableauNoir)


et vous obtenez une belle description de lutilit de votre classe. Cest trs pratique,
noubliez pas les docstrings.

Mthodes de classe et mthodes statiques


Comme on trouve des attributs propres la classe, on trouve aussi des mthodes de
classe, qui ne travaillent pas sur linstance self mais sur la classe mme. Cest un
183

CHAPITRE 17. PREMIRE APPROCHE DES CLASSES


peu plus rare mais cela peut tre utile parfois. Notre mthode de classe se dfinit
exactement comme une mthode dinstance, la diffrence quelle ne prend pas en
premier paramtre self (linstance de lobjet) mais cls (la classe de lobjet).
En outre, on utilise ensuite une fonction built-in de Python pour lui faire comprendre
quil sagit dune mthode de classe, pas dune mthode dinstance.
class Compteur :
""" Cette classe poss de un attribut de classe qui s ' incr
mente chaque
fois que l ' on cr e un objet de ce type """

1
2
3
4
5

objets_crees = 0 # Le compteur vaut 0 au d part


def __init__ ( self ) :
""" chaque fois qu ' on cr e un objet , on incr mente le
compteur """
Compteur . objets_crees += 1
def combien ( cls ) :
""" M thode de classe affichant combien d ' objets ont t
cr s """
print ( " Jusqu ' pr sent , { } objets ont t cr s . " .
format (
cls . objets_crees ) )
combien = classmethod ( combien )

6
7
8
9
10
11
12
13
14

Voyons dabord le rsultat :


1
2
3
4
5
6
7
8
9

>>> Compteur . combien ()


Jusqu pr sent , 0 objets ont t cr s .
>>> a = Compteur ()
>>> Compteur . combien ()
Jusqu pr sent , 1 objets ont t cr s .
>>> b = Compteur ()
>>> Compteur . combien ()
Jusqu pr sent , 2 objets ont t cr s .
>>>

Une mthode de classe prend en premier paramtre non pas self mais cls. Ce paramtre contient la classe (ici Compteur).
Notez que vous pouvez appeler la mthode de classe depuis un objet instanci sur la
classe. Vous auriez par exemple pu crire a.combien().
Enfin, pour que Python reconnaisse une mthode de classe, il faut appeler la fonction
classmethod qui prend en paramtre la mthode que lon veut convertir et renvoie la
mthode convertie.
Si vous tes un peu perdus, retenez la syntaxe de lexemple. La plupart du temps, vous
dfinirez des mthodes dinstance comme nous lavons vu plutt que des mthodes de
classe.
184

UN PEU DINTROSPECTION
On peut galement dfinir des mthodes statiques. Elles sont assez proches des mthodes de classe sauf quelles ne prennent aucun premier paramtre, ni self ni cls.
Elles travaillent donc indpendemment de toute donne, aussi bien contenue dans linstance de lobjet que dans la classe.
Voici la syntaxe permettant de crer une mthode statique. Je ne veux pas vous surcharger dinformations et je vous laisse faire vos propres tests si cela vous intresse :
1
2
3
4
5
6
7

class Test :
""" Une classe de test tout simplement """
def afficher () :
""" Fonction charg e d ' afficher quelque chose """
print ( " On affiche la m me chose . " )
print ( " peu importe les donn es de l ' objet ou de la
classe . " )
afficher = staticmethod ( afficher )

Si vous vous emmlez un peu avec les attributs et mthodes de classe, ce nest pas bien
grave. Retenez surtout les attributs et mthodes dinstance, cest essentiellement sur
ceux-ci que je me suis attard et cest ceux que vous retrouverez la plupart du temps.
Rappel : les noms de mthodes encadrs par deux souligns de part et dautre
sont des mthodes spciales. Ne nommez pas vos mthodes ainsi. Nous dcouvrirons plus tard ces mthodes particulires. Exemple de nom de mthode
viter : __mamethode__.

Un peu dintrospection
Encore de la philosophie ?

Eh bien. . . le terme dintrospection, je le reconnais, fait penser quelque chose de


plutt abstrait. Pourtant, vous allez trs vite comprendre lide qui se cache derrire :
Python propose plusieurs techniques pour explorer un objet, connatre ses mthodes
ou attributs.
Quel est lintrt ? Quand on dveloppe une classe, on sait gnralement ce
quil y a dedans, non ?
En effet. Lutilit, notre niveau, ne saute pas encore aux yeux. Et cest pour cela que
je ne vais pas trop mattarder dessus. Si vous ne voyez pas lintrt, contentez-vous de
garder dans un coin de votre tte les deux techniques que nous allons voir. Arrivera un
jour o vous en aurez besoin ! Pour lheure donc, voyons plutt leffet :
185

CHAPITRE 17. PREMIRE APPROCHE DES CLASSES

La fonction dir
La premire technique dintrospection que nous allons voir est la fonction dir. Elle
prend en paramtre un objet et renvoie la liste de ses attributs et mthodes.
class Test :
""" Une classe de test tout simplement """
def __init__ ( self ) :
""" On d finit dans le constructeur un unique attribut
"""
self . mon_attribut = " ok "

1
2
3
4
5
6

def afficher_attribut ( self ) :


""" M thode affichant l ' attribut ' mon_attribut ' """
print ( " Mon attribut est { 0 } . " . format ( self . mon_attribut )
)

7
8
9

1
2
3
4
5
6
7
8
9
10
11

>>> # Cr ons un objet de la classe Test


... un_test = Test ()
>>> un_test . afficher_attribut ()
Mon attribut est ok .
>>> dir ( un_test )
[ __class__ , __delattr__ , __dict__ , __doc__ , __eq__ ,
__format__ , __g
e__ , __getattribute__ , __gt__ , __hash__ , __init__ ,
__le__ , __lt__ ,
__module__ , __ne__ , __new__ , __reduce__ , __reduce_ex__
, __repr__ , _
_setattr__ , __sizeof__ , __str__ , __subclasshook__ ,
__weakref__ , affich
er_attribut , mon_attribut ]
>>>

La fonction dir renvoie une liste comprenant le nom des attributs et mthodes de
lobjet quon lui passe en paramtre. Vous pouvez remarquer que tout est mlang,
cest normal : pour Python, les mthodes, les fonctions, les classes, les modules sont
des objets. Ce qui diffrencie en premier lieu une variable dune fonction, cest quune
fonction est excutable (callable). La fonction dir se contente de renvoyer tout ce quil
y a dans lobjet, sans distinction.
Euh, cest quoi tout cela ? On na jamais dfini toutes ces mthodes ou attributs !
Non, en effet. Nous verrons plus loin quil sagit de mthodes spciales utiles
Python.
186

UN PEU DINTROSPECTION

Lattribut spcial __dict__


Par dfaut, quand vous dveloppez une classe, tous les objets construits depuis cette
classe possderont un attribut spcial __dict__. Cet attribut est un dictionnaire qui
contient en guise de cls les noms des attributs et, en tant que valeurs, les valeurs des
attributs.
Voyez plutt :
1
2
3
4

>>> un_test = Test ()


>>> un_test . __dict__
{ mon_attribut : ok }
>>>

Pourquoi attribut spcial ?

Cest un attribut un peu particulier car ce nest pas vous qui le crez, cest Python. Il
est entour de deux signes souligns __ de part et dautre, ce qui traduit quil a une
signification pour Python et nest pas un attribut standard . Vous verrez plus loin
dans ce cours des mthodes spciales qui reprennent la mme syntaxe.

Peut-on modifier ce dictionnaire ?

Vous le pouvez. Sachez quen modifiant la valeur de lattribut, vous modifiez aussi
lattribut dans lobjet.
1
2
3
4

>>> un_test . __dict__ [" mon_attribut "] = " plus ok "


>>> un_test . afficher_attribut ()
Mon attribut est plus ok .
>>>

De manire gnrale, ne faites appel lintrospection que si vous avez une bonne
raison de le faire et vitez ce genre de syntaxe. Il est quand mme plus propre dcrire
objet.attribut = valeur que objet.__dict__[nom_attribut] = valeur.
Nous nirons pas plus loin dans ce chapitre. Je pense que vous dcouvrirez dans la suite
de ce livre lutilit des deux mthodes que je vous ai montres.

En rsum
On dfinit une classe en suivant la syntaxe class NomClasse:.
Les mthodes se dfinissent comme des fonctions, sauf quelles se trouvent dans le
corps de la classe.
187

CHAPITRE 17. PREMIRE APPROCHE DES CLASSES


Les mthodes dinstance prennent en premier paramtre self, linstance de lobjet
manipul.
On construit une instance de classe en appelant son constructeur, une mthode
dinstance appele __init__.
On dfinit les attributs dune instance dans le constructeur de sa classe, en suivant
cette syntaxe : self.nom_attribut = valeur.

188

Chapitre

18

Les proprits
Difficult :

u chapitre prcdent, nous avons appris crer nos premiers attributs et mthodes.
Mais nous avons encore assez peu parl de la philosophie objet. Il existe quelques
confusions que je vais tcher de lever.

Nous allons dcouvrir dans ce chapitre les proprits, un concept propre Python et
quelques autres langages, comme le Ruby. Cest une fonctionnalit qui, elle seule, change
lapproche objet et le principe dencapsulation.

189

CHAPITRE 18. LES PROPRITS

Quest-ce que lencapsulation ?


Lencapsulation est un principe qui consiste cacher ou protger certaines donnes
de notre objet. Dans la plupart des langages orients objet, tels que le C++, le Java
ou le PHP, on va considrer que nos attributs dobjets ne doivent pas tre accessibles
depuis lextrieur de la classe. Autrement dit, vous navez pas le droit de faire, depuis
lextrieur de la classe, mon_objet.mon_attribut.
Mais cest stupide ! Comment fait-on pour accder aux attributs ?

On va dfinir des mthodes un peu particulires, appeles des accesseurs et mutateurs. Les accesseurs donnent accs lattribut. Les mutateurs permettent de le
modifier. Concrtement, au lieu dcrire mon_objet.mon_attribut, vous allez crire
mon_objet.get_mon_attribut() 1 . De la mme manire, pour modifier lattribut crivez mon_objet.set_mon_attribut(valeur) 2 et non pas mon_objet.mon_attribut =
valeur.
Cest bien tordu tout cela ! Pourquoi ne peut-on pas accder aux attributs
directement, comme on la fait au chapitre prcdent ?
Ah mais dabord, je nai pas dit que vous ne pouviez pas. Vous pouvez trs bien accder
aux attributs dun objet directement, comme on la fait au chapitre prcdent. Je ne
fais ici que rsumer le principe dencapsulation tel quon peut le trouver dans dautres
langages. En Python, cest un peu plus subtil.
Mais pour rpondre la question, il peut tre trs pratique de scuriser certaines
donnes de notre objet, par exemple faire en sorte quun attribut de notre objet ne soit
pas modifiable, ou alors mettre jour un attribut ds quun autre attribut est modifi.
Les cas sont multiples et cest trs utile de pouvoir contrler laccs en lecture ou en
criture sur certains attributs de notre objet.
Linconvnient de devoir crire des accesseurs et mutateurs, comme vous laurez sans
doute compris, cest quil faut crer deux mthodes pour chaque attribut de notre
classe. Dabord, cest assez lourd. Ensuite, nos mthodes se ressemblent plutt. Certains
environnements de dveloppement proposent, il est vrai, de crer ces accesseurs et
mutateurs pour nous, automatiquement. Mais cela ne rsout pas vraiment le problme,
vous en conviendrez.
Python a une philosophie un peu diffrente : pour tous les objets dont on nattend
pas une action particulire, on va y accder directement, comme nous lavons fait
au chapitre prcdent. On peut y accder et les modifier en crivant simplement
mon_objet.mon_attribut. Et pour certains, on va crer des proprits.
1. get signifie rcuprer , cest le prfixe gnralement utilis pour un accesseur.
2. set signifie, dans ce contexte, modifier ; cest le prfixe usuel pour un mutateur.

190

LES PROPRITS LA CASSEROLE

Les proprits la casserole


Pour commencer, une petite prcision : en C++ ou en Java par exemple, dans la
dfinition de classe, on met en place des principes daccs qui indiquent si lattribut
(ou le groupe dattributs) est priv ou public. Pour schmatiser, si lattribut est public,
on peut y accder depuis lextrieur de la classe et le modifier. Sil est priv, on ne peut
pas. On doit passer par des accesseurs ou mutateurs.
En Python, il ny a pas dattribut priv. Tout est public. Cela signifie que si vous
voulez modifier un attribut depuis lextrieur de la classe, vous le pouvez. Pour faire
respecter lencapsulation propre au langage, on la fonde sur des conventions que nous
allons dcouvrir un peu plus bas mais surtout sur le bon sens de lutilisateur de notre
classe ( savoir, si jai crit que cet attribut est inaccessible depuis lextrieur de la
classe, je ne vais pas chercher y accder depuis lextrieur de la classe).
Les proprits sont un moyen transparent de manipuler des attributs dobjet. Elles
permettent de dire Python : Quand un utilisateur souhaite modifier cet attribut,
fais cela . De cette faon, on peut rendre certains attributs tout fait inaccessibles
depuis lextrieur de la classe, ou dire quun attribut ne sera visible quen lecture et non
modifiable. Ou encore, on peut faire en sorte que, si on modifie un attribut, Python
recalcule la valeur dun autre attribut de lobjet.
Pour lutilisateur, cest absolument transparent : il croit avoir, dans tous les cas, un
accs direct lattribut. Cest dans la dfinition de la classe que vous allez prciser que
tel ou tel attribut doit tre accessible ou modifiable grce certaines proprits.
Mais ces proprits, cest quoi ?

Hum. . . eh bien je pense que pour le comprendre, il vaut mieux les voir en action.
Les proprits sont des objets un peu particuliers de Python. Elles prennent la place
dun attribut et agissent diffremment en fonction du contexte dans lequel elles sont
appeles. Si on les appelle pour modifier lattribut, par exemple, elles vont rediriger vers
une mthode que nous avons cre, qui gre le cas o on souhaite modifier lattribut .
Mais trve de thorie.

Les proprits en action


Une proprit ne se cre pas dans le constructeur mais dans le corps de la classe. Jai
dit quil sagissait dune classe, son nom est property. Elle attend quatre paramtres,
tous optionnels :

la
la
la
la

mthode
mthode
mthode
mthode

donnant accs lattribut ;


modifiant lattribut ;
appele quand on souhaite supprimer lattribut ;
appele quand on demande de laide sur lattribut.
191

CHAPITRE 18. LES PROPRITS


En pratique, on utilise surtout les deux premiers paramtres : ceux dfinissant les
mthodes daccs et de modification, autrement dit nos accesseur et mutateur dobjet.
Mais jimagine que ce nest pas trs clair dans votre esprit. Considrez le code suivant,
je le dtaillerai plus bas comme dhabitude :
1
2
3
4
5
6

class Personne :
""" Classe d finissant une personne caract ris e par :
- son nom ;
- son pr nom ;
- son ge ;
- son lieu de r sidence """

7
8
9
10
11
12
13
14
15
16
17

def __init__ ( self , nom , prenom ) :


""" Constructeur de notre classe """
self . nom = nom
self . prenom = prenom
self . age = 33
self . _lieu_residence = " Paris " # Notez le soulign _
devant le nom
def _get_lieu_residence ( self ) :
""" M thode qui sera appel e quand on souhaitera acc der en
lecture
l ' attribut ' lieu_residence ' """

18
19
20
21
22
23
24
25
26
27
28
29

print ( " On acc de l ' attribut lieu_residence ! " )


return self . _lieu_residence
def _set_lieu_residence ( self , nouvelle_residence ) :
""" M thode appel e quand on souhaite modifier le lieu
de r sidence """
print ( " Attention , il semble que { } d m nage { } . " .
format ( \
self . prenom , nouvelle_residence ) )
self . _lieu_residence = nouvelle_residence
# On va dire Python que notre attribut lieu_residence
pointe vers une
# propri t
lieu_residence = property ( _get_lieu_residence ,
_ set_lieu_residence )

Vous devriez (jespre) reconnatre la syntaxe gnrale de la classe. En revanche, au


niveau du lieu de rsidence, les choses changent un peu :
Tout dabord, dans le constructeur, on ne cre pas un attribut self.lieu_residence
mais self._lieu_residence. Il ny a quun petit caractre de diffrence, le signe
soulign _ plac en tte du nom de lattribut. Et pourtant, ce signe change beaucoup
de choses. La convention veut quon naccde pas, depuis lextrieur de la classe,
un attribut commenant par un soulign _. Cest une convention, rien ne vous
linterdit. . . sauf, encore une fois, le bon sens.
192

LES PROPRITS EN ACTION


On dfinit une premire mthode, commenant elle aussi par un soulign _, nomme
_get_lieu_residence. Cest la mme rgle que pour les attributs : on naccde pas,
depuis lextrieur de la classe, une mthode commenant par un soulign _. Si
vous avez compris ma petite explication sur les accesseurs et mutateurs, vous devriez
comprendre rapidement quoi sert cette mthode : elle se contente de renvoyer le
lieu de rsidence. L encore, lattribut manipul nest pas lieu_residence mais
_lieu_residence. Comme on est dans la classe, on a le droit de le manipuler.
La seconde mthode a la forme dun mutateur. Elle se nomme _set_lieu_residence
et doit donc aussi tre inaccessible depuis lextrieur de la classe. la diffrence de
laccesseur, elle prend un paramtre : le nouveau lieu de rsidence. En effet, cest une
mthode qui doit tre appele quand on cherche modifier le lieu de rsidence, il lui
faut donc le nouveau lieu de rsidence quon souhaite voir affect lobjet.
Enfin, la dernire ligne de la classe est trs intressante. Il sagit de la dfinition dune
proprit. On lui dit que lattribut lieu_residence (cette fois, sans signe soulign
_) doit tre une proprit. On dfinit dans notre proprit, dans lordre, la mthode
daccs (laccesseur) et celle de modification (le mutateur).
Quand on veut accder objet.lieu_residence, Python tombe sur une proprit
redirigeant vers la mthode _get_lieu_residence. Quand on souhaite modifier la
valeur de lattribut, en crivant objet.lieu_residence = valeur, Python appelle la
mthode _set_lieu_residence en lui passant en paramtre la nouvelle valeur.
Ce nest pas clair ? Voyez cet exemple :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

>>> jean = Personne (" Micado " , " Jean ")


>>> jean . nom
Micado
>>> jean . prenom
Jean
>>> jean . age
33
>>> jean . lieu_residence
On acc de l attribut lieu_residence !
Paris
>>> jean . lieu_residence = " Berlin "
Attention , il semble que Jean d m nage Berlin .
>>> jean . lieu_residence
On acc de l attribut lieu_residence !
Berlin
>>>

Notre accesseur et notre mutateur se contentent dafficher un message, pour bien quon
se rende compte que ce sont eux qui sont appels quand on souhaite manipuler lattribut
lieu_residence. Vous pouvez aussi ne dfinir quun accesseur, dans ce cas lattribut
ne pourra pas tre modifi.
Il est aussi possible de dfinir, en troisime position du constructeur property, une
mthode qui sera appele quand on fera del objet.lieu_residence et, en quatrime
position, une mthode qui sera appele quand on fera help(objet.lieu_residence).
193

CHAPITRE 18. LES PROPRITS


Ces deux dernires fonctionnalits sont un peu moins utilises mais elles existent.
Voil, vous connaissez prsent la syntaxe pour crer des proprits. Entranez-vous, ce
nest pas toujours vident au dbut. Cest un concept trs puissant, il serait dommage
de passer ct.

Rsumons le principe dencapsulation en Python


Dans cette section, je vais condenser un peu tout le chapitre. Nous avons vu quen
Python, quand on souhaite accder un attribut dun objet, on crit tout btement
objet.attribut. Par contre, on doit viter daccder ainsi des attributs ou des
mthodes commenant par un signe soulign _, question de convention. Si par hasard
une action particulire doit tre mene quand on accde un attribut, pour le lire
tout simplement, pour le modifier, le supprimer. . ., on fait appel des proprits. Pour
lutilisateur de la classe, cela revient au mme : il crit toujours objet.attribut. Mais
dans la dfinition de notre classe, nous faisons en sorte que lattribut vis soit une
proprit avec certaines mthodes, accesseur, mutateur ou autres, qui dfinissent ce
que Python doit faire quand on souhaite lire, modifier, supprimer lattribut.
Avec ce concept, on perd beaucoup moins de temps. On ne fait pas systmatiquement
un accesseur et un mutateur pour chaque attribut et le code est bien plus lisible. Cest
autant de gagn.
Certaines classes ont besoin quun traitement rcurrent soit effectu sur leurs attributs. Par exemple, quand je souhaite modifier un attribut de lobjet (nimporte quel
attribut), lobjet doit tre enregistr dans un fichier. Dans ce cas, on nutilisera pas
les proprits, qui sont plus utiles pour des cas particuliers, mais plutt des mthodes
spciales, que nous dcouvrirons au prochain chapitre.

En rsum
Les proprits permettent de contrler laccs certains attributs dune instance.
Elles se dfinissent dans le corps de la classe en suivant cette syntaxe : nom_propriete
= propriete(methode_accesseur, methode_mutateur, methode_suppression,
methode_aide).
On y fait appel ensuite en crivant objet.nom_propriete comme pour nimporte
quel attribut.
Si lon souhaite juste lire lattribut, cest la mthode dfinie comme accesseur qui est
appele.
Si lon souhaite modifier lattribut, cest la mthode mutateur, si elle est dfinie, qui
est appele.
Chacun des paramtres passer property est optionnel.

194

Chapitre

19

Les mthodes spciales


Difficult :
es mthodes spciales sont des mthodes dinstance que Python reconnat et sait
utiliser, dans certains contextes. Elles peuvent servir indiquer Python ce quil doit
faire quand il se retrouve devant une expression comme mon_objet1 + mon_objet2,
voire mon_objet[indice]. Et, encore plus fort, elles contrlent la faon dont un objet se
cre, ainsi que laccs ses attributs.

Bref, encore une fonctionnalit puissante et utile du langage, que je vous invite dcouvrir.
Prenez note du fait que je ne peux pas expliquer dans ce chapitre la totalit des mthodes
spciales. Il y en a qui ne sont pas de notre niveau, il y en a sur lesquelles je passerai plus
vite que dautres. En cas de doute, ou si vous tes curieux, je vous encourage dautant plus
aller faire un tour sur le site officiel de Python.

195

CHAPITRE 19. LES MTHODES SPCIALES

dition de lobjet et accs aux attributs


Vous avez dj vu, ds le dbut de cette troisime partie, un exemple de mthode spciale. Pour ceux qui ont la mmoire courte, il sagit de notre constructeur. Une mthode
spciale, en Python, voit son nom entour de part et dautre par deux signes soulign
_. Le nom dune mthode spciale prend donc la forme : __methodespeciale__.
Pour commencer, nous allons voir les mthodes qui travaillent directement sur lobjet.
Nous verrons ensuite, plus spcifiquement, les mthodes qui permettent daccder aux
attributs.

dition de lobjet
Les mthodes que nous allons voir permettent de travailler sur lobjet. Elles interviennent au moment de le crer et au moment de le supprimer. La premire, vous
devriez la reconnatre : cest notre constructeur. Elle sappelle __init__, prend un
nombre variable darguments et permet de contrler la cration de nos attributs.
1
2
3
4
5
6

class Exemple :
""" Un petit exemple de classe """
def __init__ ( self , nom ) :
""" Exemple de constructeur """
self . nom = nom
self . autre_attribut = " une valeur "

Pour crer notre objet, nous utilisons le nom de la classe et nous passons, entre parenthses, les informations quattend notre constructeur :
1

mon_objet = Exemple ( " un premier exemple " )

Jai un peu simplifi ce qui se passe mais, pour linstant, cest tout ce quil vous faut
retenir. Comme vous pouvez le voir, partir du moment o lobjet est cr, on peut
accder ses attributs grce mon_objet.nom_attribut et excuter ses mthodes
grce mon_objet.nom_methode(...).
Il existe galement une autre mthode, __del__, qui va tre appele au moment de la
destruction de lobjet.
La destruction ? Quand un objet se dtruit-il ?

Bonne question. Il y a plusieurs cas : dabord, quand vous voulez le supprimer explicitement, grce au mot-cl del (del mon_objet). Ensuite, si lespace de noms contenant
lobjet est dtruit, lobjet lest galement. Par exemple, si vous instanciez lobjet dans
le corps dune fonction : la fin de lappel la fonction, la mthode __del__ de lobjet
sera appele. Enfin, si votre objet rsiste envers et contre tout pendant lexcution du
programme, il sera supprim la fin de lexcution.
196

DITION DE LOBJET ET ACCS AUX ATTRIBUTS


1
2
3

def __del__ ( self ) :


""" M thode appel e quand l ' objet est supprim """
print ( " C ' est la fin ! On me supprime ! " )

quoi cela peut-il bien servir, de contrler la destruction dun objet ?

Souvent, rien. Python sen sort comme un grand garon, il na pas besoin daide.
Parfois, on peut vouloir rcuprer des informations dtat sur lobjet au moment de
sa suppression. Mais ce nest quun exemple : les mthodes spciales sont un moyen
dexcuter des actions personnalises sur certains objets, dans un cas prcis. Si lutilit
ne saute pas aux yeux, vous pourrez en trouver une un beau jour, en codant votre
projet.
Souvenez-vous que si vous ne dfinissez pas de mthode spciale pour telle ou telle
action, Python aura un comportement par dfaut dans le contexte o cette mthode
est appele. crire une mthode spciale permet de modifier ce comportement par
dfaut. Dans labsolu, vous ntes mme pas obligs dcrire un constructeur.

Reprsentation de lobjet
Nous allons voir deux mthodes spciales qui permettent de contrler comment lobjet
est reprsent et affich. Vous avez srement dj pu constater que, quand on instancie
des objets issus de nos propres classes, si on essaye de les afficher directement dans
linterprteur ou grce print, on obtient quelque chose dassez laid :
1

< __main__ . XXX object at 0x00B46A70 >

On a certes les informations utiles, mais pas forcment celles quon veut, et lensemble
nest pas magnifique, il faut bien le reconnatre.
La premire mthode permettant de remdier cet tat de fait est __repr__. Elle
affecte la faon dont est affich lobjet quand on tape directement son nom. On la
redfinit quand on souhaite faciliter le debug sur certains objets :
1
2
3
4
5
6
7
8
9
10
11

class Personne :
""" Classe repr sentant une personne """
def __init__ ( self , nom , prenom ) :
""" Constructeur de notre classe """
self . nom = nom
self . prenom = prenom
self . age = 33
def __repr__ ( self ) :
""" Quand on entre notre objet dans l ' interpr teur """
return " Personne : nom ( { } ) , pr nom ( { } ) , ge ( { } ) " . format (
self . nom , self . prenom , self . age )

Et le rsultat en images :
197

CHAPITRE 19. LES MTHODES SPCIALES

>>> p1 = Personne (" Micado " , " Jean ")


>>> p1
Personne : nom ( Micado ) , pr nom ( Jean ) , ge (33)
>>>

1
2
3
4

Comme vous le voyez, la mthode __repr__ ne prend aucun paramtre (sauf, bien
entendu, self) et renvoie une chane de caractres : la chane afficher quand on entre
lobjet directement dans linterprteur.
On peut galement obtenir cette chane grce la fonction repr, qui se contente dappeler la mthode spciale __repr__ de lobjet pass en paramtre :
1
2
3
4

>>> p1 = Personne (" Micado " , " Jean ")


>>> repr ( p1 )
Personne : nom ( Micado ) , pr nom ( Jean ) , ge (33)
>>>

Il existe une seconde mthode spciale, __str__, spcialement utilise pour afficher
lobjet avec print. Par dfaut, si aucune mthode __str__ nest dfinie, Python appelle
la mthode __repr__ de lobjet. La mthode __str__ est galement appele si vous
dsirez convertir votre objet en chane avec le constructeur str.
class Personne :
""" Classe repr sentant une personne """
def __init__ ( self , nom , prenom ) :
""" Constructeur de notre classe """
self . nom = nom
self . prenom = prenom
self . age = 33
def __str__ ( self ) :
""" M thode permettant d ' afficher plus joliment notre
objet """
return " { } { } , g de { } ans " . format (
self . prenom , self . nom , self . age )

1
2
3
4
5
6
7
8
9
10
11

Et en pratique :
1
2
3
4
5
6
7

>>> p1 = Personne (" Micado " , " Jean ")


>>> print ( p1 )
Jean Micado , g de 33 ans
>>> chaine = str ( p1 )
>>> chaine
Jean Micado , g de 33 ans
>>>

198

DITION DE LOBJET ET ACCS AUX ATTRIBUTS

Accs aux attributs de notre objet


Nous allons dcouvrir trois mthodes permettant de dfinir comment accder nos
attributs et les modifier.
La mthode __getattr__
La mthode spciale __getattr__ permet de dfinir une mthode daccs nos attributs plus large que celle que Python propose par dfaut. En fait, cette mthode
est appele quand vous tapez objet.attribut (non pas pour modifier lattribut mais
simplement pour y accder). Python recherche lattribut et, sil ne le trouve pas dans
lobjet et si une mthode __getattr__ existe, il va lappeler en lui passant en paramtre
le nom de lattribut recherch, sous la forme dune chane de caractres.
Un petit exemple ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

>>> class Protege :


...
""" Classe poss dant une m thode particuli re d acc s
ses attributs :
...
Si l attribut n est pas trouv , on affiche une alerte
et renvoie None """
...
...
...
def __init__ ( self ) :
...
""" On cr e quelques attributs par d faut """
...
self . a = 1
...
self . b = 2
...
self . c = 3
...
def __getattr__ ( self , nom ) :
...
""" Si Python ne trouve pas l attribut nomm nom , il
appelle
...
cette m thode . On affiche une alerte """
...
...
...
print (" Alerte ! Il n y a pas d attribut {} ici !".
format ( nom ) )
...
>>> pro = Protege ()
>>> pro . a
1
>>> pro . c
3
>>> pro . e
Alerte ! Il n y a pas d attribut e ici !
>>>

Vous comprenez le principe ? Si lattribut auquel on souhaite accder existe, notre


mthode nest pas appele. En revanche, si lattribut nexiste pas, notre mthode
__getattr__ est appele. On lui passe en paramtre le nom de lattribut auquel Py199

CHAPITRE 19. LES MTHODES SPCIALES


thon essaye daccder. Ici, on se contente dafficher une alerte. Mais on pourrait tout
aussi bien rediriger vers un autre attribut. Par exemple, si on essaye daccder un
attribut qui nexiste pas, on redirige vers self.c. Je vous laisse faire lessai, cela na
rien de difficile.
La mthode __setattr__
Cette mthode dfinit laccs un attribut destin tre modifi. Si vous crivez
objet.nom_attribut = nouvelle_valeur, la mthode spciale __setattr__ sera appele ainsi : objet.__setattr__("nom_attribut", nouvelle_valeur). L encore, le
nom de lattribut recherch est pass sous la forme dune chane de caractres. Cette
mthode permet de dclencher une action ds quun attribut est modifi, par exemple
enregistrer lobjet :
1
2
3

def __setattr__ ( self , nom_attr , val_attr ) :


""" M thode appel e quand on fait objet . nom_attr =
val_attr .
On se charge d ' enregistrer l ' objet """

4
5
6
7

object . __setattr__ ( self , nom_attr , val_attr )


self . enregistrer ()

Une explication simpose concernant la ligne 6, je pense. Je vais faire de mon mieux,
sachant que jexpliquerai bien plus en dtail, dans un prochain chapitre, le concept
dhritage. Pour linstant, il vous suffit de savoir que toutes les classes que nous crons
sont hrites de la classe object. Cela veut dire essentiellement quelles reprennent les
mmes mthodes. La classe object est dfinie par Python. Je disais plus haut que, si
vous ne dfinissiez pas une certaine mthode spciale, Python avait un comportement
par dfaut : ce comportement est dfini par la classe object.
La plupart des mthodes spciales sont dclares dans object. Si vous faites par
exemple objet.attribut = valeur sans avoir dfini de mthode __setattr__ dans
votre classe, cest la mthode __setattr__ de la classe object qui sera appele.
Mais si vous redfinissez la mthode __setattr__ dans votre classe, la mthode appele
sera alors celle que vous dfinissez, et non celle de object. Oui mais. . . vous ne savez pas
comment Python fait, rellement, pour modifier la valeur dun attribut. Le mcanisme
derrire la mthode vous est inconnu.
Si vous essayez, dans la mthode __setattr__, de faire self.attribut = valeur,
vous allez crer une jolie erreur : Python va vouloir modifier un attribut, il appelle la
mthode __setattr__ de la classe que vous avez dfinie, il tombe dans cette mthode
sur une nouvelle affectation dattribut, il appelle donc de nouveau __setattr__. . . et
tout cela, jusqu linfini ou presque. Python met en place une protection pour viter
quune mthode ne sappelle elle-mme linfini, mais cela ne rgle pas le problme.
Tout cela pour dire que, dans votre mthode __setattr__, vous ne pouvez pas modifier
dattribut de la faon que vous connaissez. Si vous le faites, __setattr__ appellera
__setattr__ qui appellera __setattr__. . . linfini. Donc si on souhaite modifier un
200

DITION DE LOBJET ET ACCS AUX ATTRIBUTS


attribut, on va se rfrer la mthode __setattr__ dfinie dans la classe object, la
classe mre dont toutes nos classes hritent.
Si toutes ces explications vous ont paru plutt dures, ne vous en faites pas trop : je
dtaillerai dans un prochain chapitre ce quest lhritage, vous comprendrez srement
mieux ce moment.

La mthode __delattr__
Cette mthode spciale est appele quand on souhaite supprimer un attribut de lobjet,
en faisant del objet.attribut par exemple. Elle prend en paramtre, outre self, le
nom de lattribut que lon souhaite supprimer. Voici un exemple dune classe dont on
ne peut supprimer aucun attribut :
1
2
3

def __delattr__ ( self , nom_attr ) :


""" On ne peut supprimer d ' attribut , on l ve l ' exception
AttributeError """

4
5

raise AttributeError ( " Vous ne pouvez supprimer aucun


attribut de cette classe " )

L encore, si vous voulez supprimer un attribut, nutilisez pas dans votre mthode
del self.attribut. Sinon, vous risquez de mettre Python trs en colre ! Passez par
object.__delattr__ qui sait mieux que nous comment tout cela fonctionne.

Un petit bonus
Voici quelques fonctions qui font peu prs ce que nous avons fait mais en utilisant
des chanes de caractres pour les noms dattributs. Vous pourrez en avoir lusage :
1
2
3
4
5

objet = MaClasse () # On cr e une instance de notre classe


getattr ( objet , " nom " ) # Semblable objet . nom
setattr ( objet , " nom " , val ) # = objet . nom = val ou objet .
__setattr__ (" nom " , val )
delattr ( objet , " nom " ) # = del objet . nom ou objet . __delattr__ ("
nom ")
hasattr ( objet , " nom " ) # Renvoie True si l ' attribut " nom " existe
, False sinon

Peut-tre ne voyez-vous pas trop lintrt de ces fonctions qui prennent toutes, en
premier paramtre, lobjet sur lequel travailler et en second le nom de lattribut (sous
la forme dune chane). Toutefois, cela peut tre trs pratique parfois de travailler avec
des chanes de caractres plutt quavec des noms dattributs. Dailleurs, cest un peu
ce que nous venons de faire, dans nos redfinitions de mthodes accdant aux attributs.
L encore, si lintrt ne saute pas aux yeux, laissez ces fonctions de ct. Vous pourrez
les retrouver par la suite.
201

CHAPITRE 19. LES MTHODES SPCIALES

Les mthodes de conteneur


Nous allons commencer travailler sur ce que lon appelle la surcharge doprateurs.
Il sagit assez simplement dexpliquer Python quoi faire quand on utilise tel ou tel
oprateur. Nous allons ici voir quatre mthodes spciales qui interviennent quand on
travaille sur des objets conteneurs.

Accs aux lments dun conteneur


Les objets conteneurs, jespre que vous vous en souvenez, ce sont les chanes de caractres, les listes et les dictionnaires, entre autres. Tous ont un point commun : ils
contiennent dautres objets, auxquels on peut accder grce loprateur [].
Les trois premires mthodes que nous allons voir sont __getitem__, __setitem__ et
__delitem__. Elles servent respectivement dfinir quoi faire quand on crit :
objet[index] ;
objet[index] = valeur ;
del objet[index] ;
Pour cet exemple, nous allons voir une classe enveloppe de dictionnaire. Les classes
enveloppes sont des classes qui ressemblent dautres classes mais nen sont pas rellement. Cela vous avance ?
Nous allons crer une classe que nous allons appeler ZDict. Elle va possder un attribut
auquel on ne devra pas accder de lextrieur de la classe, un dictionnaire que nous
appellerons _dictionnaire. Quand on crera un objet de type ZDict et quon voudra
faire objet[index], lintrieur de la classe on fera self._dictionnaire[index].
En ralit, notre classe fera semblant dtre un dictionnaire, elle ragira de la mme
manire, mais elle nen sera pas rellement un.
1
2
3
4
5
6
7
8

class ZDict :
""" Classe enveloppe d ' un dictionnaire """
def __init__ ( self ) :
""" Notre classe n ' accepte aucun param tre """
self . _dictionnaire = { }
def __getitem__ ( self , index ) :
""" Cette m thode sp ciale est appel e quand on fait
objet [ index ]
Elle redirige vers self . _dictionnaire [ index ] """

9
10
11
12
13

return self . _dictionnaire [ index ]


def __setitem__ ( self , index , valeur ) :
""" Cette m thode est appel e quand on crit objet [ index
] = valeur
On redirige vers self . _dictionnaire [ index ] = valeur """

14
15

self . _dictionnaire [ index ] = valeur

Vous avez un exemple dutilisation des deux mthodes __getitem__ et __setitem__


202

LES MTHODES MATHMATIQUES


qui, je pense, est assez clair. Pour __delitem__, je crois que cest assez vident, elle ne
prend quun seul paramtre qui est lindex que lon souhaite supprimer. Vous pouvez
tendre cet exemple avec dautres mthodes que nous avons vues plus haut, notamment
__repr__ et __str__. Nhsitez pas, entranez-vous, tout cela peut vous servir.

La mthode spciale derrire le mot-cl in


Il existe une quatrime mthode, appele __contains__, qui est utilise quand on
souhaite savoir si un objet se trouve dans un conteneur.
Exemple classique :
1
2
3

ma_liste = [1 , 2 , 3 , 4 , 5 ]
8 in ma_liste # Revient au m me que ...
ma_liste . __contains__ ( 8 )

Ainsi, si vous voulez que votre classe enveloppe puisse utiliser le mot-cl in comme une
liste ou un dictionnaire, vous devez redfinir cette mthode __contains__ qui prend
en paramtre, outre self, lobjet qui nous intresse. Si lobjet est dans le conteneur,
on doit renvoyer True ; sinon False.
Je vous laisse redfinir cette mthode, vous avez toutes les indications ncessaires.

Connatre la taille dun conteneur


Il existe enfin une mthode spciale __len__, appele quand on souhaite connatre la
taille dun objet conteneur, grce la fonction len.
len(objet) quivaut objet.__len__(). Cette mthode spciale ne prend aucun
paramtre et renvoie une taille sous la forme dun entier. L encore, je vous laisse faire
lessai.

Les mthodes mathmatiques


Pour cette section, nous allons continuer voir les mthodes spciales permettant la
surcharge doprateurs mathmatiques, comme +, -, * et jen passe.

Ce quil faut savoir


Pour cette section, nous allons utiliser un nouvel exemple, une classe capable de contenir
des dures. Ces dures seront contenues sous la forme dun nombre de minutes et un
nombre de secondes.
Voici le corps de la classe, gardez-le sous la main :
1
2

class Duree :
""" Classe contenant des dur es sous la forme d ' un nombre de
minutes

203

CHAPITRE 19. LES MTHODES SPCIALES


et de secondes """

3
4

def __init__ ( self , min =0 , sec = 0 ) :


""" Constructeur de la classe """
self . min = min # Nombre de minutes
self . sec = sec # Nombre de secondes
def __str__ ( self ) :
""" Affichage un peu plus joli de nos objets """
return " { 0 : 02 } : { 1 : 02 } " . format ( self . min , self . sec )

5
6
7
8
9
10
11

On dfinit simplement deux attributs contenant notre nombre de minutes et notre


nombre de secondes, ainsi quune mthode pour afficher tout cela un peu mieux. Si
vous vous interrogez sur lutilisation de la mthode format dans la mthode __str__,
sachez simplement que le but est de voir la dure sous la forme MM:SS ; pour plus
dinformations sur le formatage des chanes, vous pouvez consulter le code web suivant :


Documentation de Python
B
Code web : 973909


Crons un premier objet Duree que nous appelons d1.
>>> d1 = Duree (3 , 5)
>>> print ( d1 )
03:05
>>>

1
2
3
4

Si vous essayez de faire d1 + 4, par exemple, vous allez obtenir une erreur. Python ne
sait pas comment additionner un type Duree et un int. Il ne sait mme pas comment
ajouter deux dures ! Nous allons donc lui expliquer.
La mthode spciale redfinir est __add__. Elle prend en paramtre lobjet que lon
souhaite ajouter. Voici deux lignes de code qui reviennent au mme :
1
2

d1 + 4
d1 . __add__ ( 4 )

Comme vous le voyez, quand vous utilisez le symbole + ainsi, cest en fait la mthode
__add__ de lobjet Duree qui est appele. Elle prend en paramtre lobjet que lon
souhaite ajouter, peu importe le type de lobjet en question. Et elle doit renvoyer un
objet exploitable, ici il serait plus logique que ce soit une nouvelle dure.
Si vous devez faire diffrentes actions en fonction du type de lobjet ajouter, testez
le rsultat de type(objet_a_ajouter).
1
2
3
4
5
6

def __add__ ( self , objet_a_ajouter ) :


""" L ' objet ajouter est un entier , le nombre de
secondes """
nouvelle_duree = Duree ()
# On va copier self dans l ' objet cr pour avoir la m
me dur e
nouvelle_duree . min = self . min
nouvelle_duree . sec = self . sec

204

LES MTHODES MATHMATIQUES


7
8
9
10
11
12
13
14

# On ajoute la dur e
nouvelle_duree . sec += objet_a_ajouter
# Si le nombre de secondes >= 60
if nouvelle_duree . sec >= 60 :
nouvelle_duree . min += nouvelle_duree . sec // 60
nouvelle_duree . sec = nouvelle_duree . sec % 60
# On renvoie la nouvelle dur e
return nouvelle_duree

Prenez le temps de comprendre le mcanisme et le petit calcul pour vous assurer davoir
une dure cohrente. Dabord, on cre une nouvelle dure qui est lquivalent de la dure
contenue dans self. On laugmente du nombre de secondes ajouter et on sassure
que le temps est cohrent (le nombre de secondes natteint pas 60). Si le temps nest
pas cohrent, on le corrige. On renvoie enfin notre nouvel objet modifi. Voici un petit
code qui montre comment utiliser notre mthode :
1
2
3
4
5
6
7

>>> d1 = Duree (12 , 8)


>>> print ( d1 )
12:08
>>> d2 = d1 + 54 # d1 + 54 secondes
>>> print ( d2 )
13:02
>>>

Pour mieux comprendre, remplacez d2 = d1 + 54 par d2 = d1.__add__(54) : cela


revient au mme. Ce remplacement ne sert qu bien comprendre le mcanisme. Il va
de soi que ces mthodes spciales ne sont pas appeler directement depuis lextrieur
de la classe, les oprateurs nont pas t invents pour rien.
Sachez que sur le mme modle, il existe les mthodes :

__sub__ : surcharge de loprateur - ;


__mul__ : surcharge de loprateur * ;
__truediv__ : surcharge de loprateur / ;
__floordiv__ : surcharge de loprateur // (division entire) ;
__mod__ : surcharge de loprateur % (modulo) ;
__pow__ : surcharge de loprateur ** (puissance) ;
...

Il y en a dautres que vous pouvez consulter grce au code web suivant.




Site officiel de Python
B
Code web : 338274

Tout dpend du sens


Vous lavez peut-tre remarqu, et cest assez logique si vous avez suivi mes explications,
mais crire objet1 + objet2 ne revient pas au mme qucrire objet2 + objet1 si
les deux objets ont des types diffrents.
205

CHAPITRE 19. LES MTHODES SPCIALES


En effet, suivant le cas, cest la mthode __add__ de lun ou lautre des objets qui est
appele.
Cela signifie que, lorsquon utilise la classe Duree, si on crit d1 + 4 cela fonctionne,
alors que 4 + d1 ne marche pas. En effet, la class int ne sait pas quoi faire de votre
objet Duree.
Il existe cependant une panoplie de mthodes spciales pour faire le travail de __add__
si vous crivez lopration dans lautre sens. Il suffit de prfixer le nom des mthodes
spciales par un r.
1
2
3
4
5
6

def __radd__ ( self , objet_a_ajouter ) :


""" Cette m thode est appel e si on crit 4 + objet et
que
le premier objet ( 4 dans cet exemple ) ne sait pas
comment ajouter
le second . On se contente de rediriger sur __add__
puisque ,
ici , cela revient au m me : l ' op ration doit avoir le m
me r sultat ,
pos e dans un sens ou dans l ' autre """

return self + objet_a_ajouter

prsent, on peut crire 4 + d1, cela revient au mme que d1 + 4.


Nhsitez pas relire ces exemples sils vous paraissent peu clairs.

Dautres oprateurs
Il est galement possible de surcharger les oprateurs +=, -=, etc. On prfixe cette fois-ci
les noms de mthode que nous avons vus par un i.
Exemple de mthode __iadd__ pour notre classe Duree :
1
2
3
4
5
6
7
8
9
10
11

def __iadd__ ( self , objet_a_ajouter ) :


""" L ' objet ajouter est un entier , le nombre de
secondes """
# On travaille directement sur self cette fois
# On ajoute la dur e
self . sec += objet_a_ajouter
# Si le nombre de secondes >= 60
if self . sec >= 60 :
self . min += self . sec // 60
self . sec = self . sec % 60
# On renvoie self
return self

Et en images :
1
2

206

>>> d1 = Duree (8 , 5)
>>> d1 += 128

LES MTHODES DE COMPARAISON


>>> print ( d1 )
10:13
>>>

3
4
5

Je ne peux que vous encourager faire des tests, pour tre bien srs de comprendre
le mcanisme. Je vous ai donn ici une faon de faire en la commentant mais, si vous
ne pratiquez pas ou nessayez pas par vous-mmes, vous nallez pas la retenir et vous
nallez pas forcment comprendre la logique.

Les mthodes de comparaison


Pour finir, nous allons voir la surcharge des oprateurs de comparaison que vous
connaissez depuis quelque temps maintenant : ==, !=, <, >, <=, >=.
Ces mthodes sont donc appeles si vous tentez de comparer deux objets entre eux.
Comment Python sait-il que 3 est infrieur 18 ? Une mthode spciale de la classe int
le permet, en simplifiant. Donc si vous voulez comparer des dures, par exemple, vous
allez devoir redfinir certaines mthodes que je vais prsenter plus bas. Elles devront
prendre en paramtre lobjet comparer self, et doivent renvoyer un boolen (True
ou False).
Je vais me contenter de vous faire un petit tableau rcapitulatif des mthodes redfinir
pour comparer deux objets entre eux :
Oprateur
==

Mthode spciale
def __eq__(self,
objet_a_comparer):

!=

def __ne__(self,
objet_a_comparer):

>

def __gt__(self,
objet_a_comparer):
def __ge__(self,
objet_a_comparer):
def __lt__(self,
objet_a_comparer):
def __le__(self,
objet_a_comparer):

>=
<
<=

Rsum
Oprateur dgalit (equal ). Renvoie True
si self et objet_a_comparer sont gaux,
False sinon.
Diffrent de (non equal ). Renvoie True si
self et objet_a_comparer sont diffrents,
False sinon.
Teste si self est strictement suprieur
(greather than) objet_a_comparer.
Teste si self est suprieur ou gal (greater
or equal ) objet_a_comparer.
Teste si self est strictement infrieur (lower than) objet_a_comparer.
Teste si self est infrieur ou gal (lower
or equal ) objet_a_comparer.

Sachez que ce sont ces mthodes spciales qui sont appeles si, par exemple, vous voulez
trier une liste contenant vos objets.
Sachez galement que, si Python narrive pas faire objet1 < objet2, il essayera
lopration inverse, soit objet2 >= objet1. Cela vaut aussi pour les autres oprateurs
de comparaison que nous venons de voir.
207

CHAPITRE 19. LES MTHODES SPCIALES


Allez, je vais vous mettre deux exemples malgr tout, il ne tient qu vous de redfinir
les autres mthodes prsentes plus haut :
1
2
3
4
5
6
7
8
9

def __eq__ ( self , autre_duree ) :


""" Test si self et autre_duree sont gales """
return self . sec == autre_duree . sec and self . min ==
autre_duree . min
def __gt__ ( self , autre_duree ) :
""" Test si self > autre_duree """
# On calcule le nombre de secondes de self et
autre_duree
nb_sec1 = self . sec + self . min * 60
nb_sec2 = autre_duree . sec + autre_duree . min * 60
return nb_sec1 > nb_sec2

Ces exemples devraient vous suffire, je pense.

Des mthodes spciales utiles pickle


Vous vous souvenez de pickle, jespre. Pour conclure ce chapitre sur les mthodes
spciales, nous allons en voir deux qui sont utilises par ce module pour influencer la
faon dont nos objets sont enregistrs dans des fichiers.
Prenons un cas concret, dune utilit pratique discutable.
On cre une classe qui va contenir plusieurs attributs. Un de ces attributs possde
une valeur temporaire, qui nest utile que pendant lexcution du programme. Si on
arrte ce programme et quon le relance, on doit rcuprer le mme objet mais la valeur
temporaire doit tre remise 0, par exemple.
Il y a dautres moyens dy parvenir, je le reconnais. Mais les autres applications que
jai en tte sont plus dures dvelopper et expliquer rapidement, donc gardons cet
exemple.

La mthode spciale __getstate__


La mthode __getstate__ est appele au moment de srialiser lobjet. Quand vous
voulez enregistrer lobjet laide du module pickle, __getstate__ va tre appele
juste avant lenregistrement.
Si aucune mthode __getstate__ nest dfinie, pickle enregistre le dictionnaire des attributs de lobjet enregistrer. Vous vous rappelez ? Il est contenu dans objet.__dict__.
Sinon, pickle enregistre dans le fichier la valeur renvoye par __getstate__ (gnralement, un dictionnaire dattributs modifi).
Voyons un peu comment coder notre exemple grce __getstate__ :
1
2

208

class Temp :
""" Classe contenant plusieurs attributs , dont un temporaire
"""

DES MTHODES SPCIALES UTILES PICKLE


3
4
5
6
7
8

def __init__ ( self ) :


""" Constructeur de notre objet """
self . attribut_1 = " une valeur "
self . attribut_2 = " une autre valeur "
self . attribut_temporaire = 5

9
10
11
12
13
14

def __getstate__ ( self ) :


""" Renvoie le dictionnaire d ' attributs s rialiser """
dict_attr = dict ( self . __dict__ )
dict_attr [ " attribut_temporaire " ] = 0
return dict_attr

Avant de revenir sur le code, vous pouvez en voir les effets. Si vous tentez denregistrer
cet objet grce pickle et que vous le rcuprez ensuite depuis le fichier, vous constatez
que lattribut attribut_temporaire est 0, peu importe sa valeur dorigine.
Voyons le code de __getstate__. La mthode ne prend aucun argument (except self
puisque cest une mthode dinstance).
Elle enregistre le dictionnaire des attributs dans une variable locale dict_attr. Ce
dictionnaire a le mme contenu que self.__dict__ (le dictionnaire des attributs de
lobjet). En revanche, il a une rfrence diffrente. Sans cela, la ligne suivante, au moment de modifier attribut_temporaire, le changement aurait t galement appliqu
lobjet, ce que lon veut viter.
la ligne suivante, donc, on change la valeur de lattribut attribut_temporaire.
tant donn que dict_attr et self.__dict__ nont pas la mme rfrence, lattribut
nest chang que dans dict_attr et le dictionnaire de self nest pas modifi.
Enfin, on renvoie dict_attr. Au lieu denregistrer dans notre fichier self.__dict__,
pickle enregistre notre dictionnaire modifi, dict_attr.
Si ce nest pas assez clair, je vous encourage tester par vous-mmes, essayez de modifier
la mthode __getstate__ et manipulez self.__dict__ pour bien comprendre le code.

La mthode __setstate__
la diffrence de __getstate__, la mthode __setstate__ est appele au moment
de dsrialiser lobjet. Concrtement, si vous rcuprez un objet partir dun fichier
srialis, __setstate__ sera appele aprs la rcupration du dictionnaire des attributs.
Pour schmatiser, voici lexcution que lon va observer derrire unpickler.load() :
1. Lobjet Unpickler lit le fichier.
2. Il rcupre le dictionnaire des attributs. Je vous rappelle que si aucune mthode
__getstate__ nest dfinie dans notre classe, ce dictionnaire est celui contenu
dans lattribut spcial __dict__ de lobjet au moment de sa srialisation.
3. Ce dictionnaire rcupr est envoy la mthode __setstate__ si elle existe.
Si elle nexiste pas, Python considre que cest le dictionnaire des attributs de
209

CHAPITRE 19. LES MTHODES SPCIALES


lobjet rcuprer et crit donc lattribut __dict__ de lobjet en y plaant ce
dictionnaire rcupr.
Le mme exemple mais, cette fois, par la mthode __setstate__ :
1

...

2
3
4
5

def \ _ \ _setstate \ _ \ _ ( self , dict \ _attr ) :


""" M thode appel e lors de la d s rialisation de l '
objet """
dict \ _attr [ " attribut \ _temporaire " ] = 0
self .\ _ \ _dict \ _ \ _ = dict \ _attr

Quelle est la diffrence entre les deux mthodes que nous avons vues ?

Lobjectif que nous nous tions fix peut tre atteint par ces deux mthodes. Soit notre
classe met en uvre une mthode __getstate__, soit elle met en uvre une mthode
__setstate__.
Dans le premier cas, on modifie le dictionnaire des attributs avant la srialisation. Le
dictionnaire des attributs enregistr est celui que nous avons modifi avec la valeur de
notre attribut temporaire 0.
Dans le second cas, on modifie le dictionnaire dattributs aprs la dsrialisation. Le
dictionnaire que lon rcupre contient un attribut attribut_temporaire avec une
valeur quelconque (on ne sait pas laquelle) mais avant de rcuprer lobjet, on met
cette valeur 0.
Ce sont deux moyens diffrents, qui ici reviennent au mme. vous de choisir la
meilleure mthode en fonction de vos besoins (les deux peuvent tre prsentes dans la
mme classe si ncessaire).
L encore, je vous encourage faire des essais si ce nest pas trs clair.

On peut enregistrer dans un fichier autre chose que des dictionnaires


Votre mthode __getstate__ nest pas oblige de renvoyer un dictionnaire dattributs.
Elle peut renvoyer un autre objet, un entier, un flottant, mais dans ce cas une mthode
__setstate__ devra exister pour savoir quoi faire avec lobjet enregistr. Si ce nest
pas un dictionnaire dattributs, Python ne peut pas le deviner !
L encore, je vous laisse tester si cela vous intresse.

Je veux encore plus puissant !


__getstate__ et __setstate__ sont les deux mthodes les plus connues pour agir sur
la srialisation dobjets. Mais il en existe dautres, plus complexes.
210

DES MTHODES SPCIALES UTILES PICKLE


Si vous tes intresss, jetez un il du ct de la PEP 307 via le code web suivant :


PEP 307
B
Code web : 665199

En rsum
Les mthodes spciales permettent dinfluencer la manire dont Python accde aux
attributs dune instance et ragit certains oprateurs ou conversions.
Les mthodes spciales sont toutes entoures de deux signes soulign (_).
Les mthodes __getattr__, __setattr__ et __delattr__ contrlent laccs aux
attributs de linstance.
Les mthodes __getitem__, __setitem__ et __delitem__ surchargent lindexation
([]).
Les mthodes __add__, __sub__, __mul__. . . surchargent les oprateurs mathmatiques.
Les mthodes __eq__, __ne__, __gt__. . . surchargent les oprateurs de comparaison.

211

CHAPITRE 19. LES MTHODES SPCIALES

212

Chapitre

20

Parenthse sur le tri en Python


Difficult :
Trier une liste dinformations quelconque peut savrer trs utile. . . et souvent difficile.
Python nous offre plusieurs techniques pour trier, que ce soit de simples listes de nombres,
de chanes de caractres ou de donnes plus complexes (comme des objets dont nous avons
cr nous-mmes les classes).
Ce chapitre est une parenthse : vous pouvez aller tout de suite au chapitre suivant sans
problme, et revenir celui-ci plus tard.

213

CHAPITRE 20. PARENTHSE SUR LE TRI EN PYTHON

Premire approche du tri


La premire question que vous devriez vous poser : on a une liste, on veut la trier, mais
que veut-on dire par trier ?
Trier, cest ordonner la liste dune faon cohrente. Par exemple, on pourrait vouloir
trier une liste de noms par ordre alphabtique. Ou on pourrait vouloir trier une liste
de nombres du plus petit au plus grand.
Dans tous les cas, trier une liste cest la rordonner (changer son ordre, si ncessaire)
selon certains critres. Il est important que vous gardiez en tte cette notion de critres par la suite, car nous allons en reparler.

Deux mthodes
Pour trier une squence de donnes, Python nous propose deux mthodes :
1. La premire est une mthode de liste. Elle sappelle tout simplement sort (trier
en anglais). Elle travaille sur la liste-mme et change donc son ordre, si cest
ncessaire.
2. La seconde est la fonction sorted. Il sagit dune fonction builtin, cest--dire
quelle est disponible doffice dans Python sans avoir besoin dimporter quoique
ce soit. Contrairement la mthode sort de la class list, sorted travaille sur nimporte quel type de squence (tuple, liste ou mme dictionnaire). Une importante
diffrence avec la mthode list.sort est quelle ne modifie pas lobjet dorigine,
mais en retourne un nouveau.
Voyons quelques exemples :
1
2
3
4
5
6
7
8
9
10
11

>>> prenoms = [ " Jacques " , " Laure " , " Andr " , " Victoire " , " Albert
" , " Sophie " ]
>>> prenoms . sort ()
>>> prenoms
[ ' Albert ' , ' Andr ' , ' Jacques ' , ' Laure ' , ' Sophie ' , ' Victoire ']
>>> # Et avec la fonction ' sorted '
... prenoms = [ " Jacques " , " Laure " , " Andr " , " Victoire " , " Albert
" , " Sophie " ]
>>> sorted ( prenoms )
[ ' Albert ' , ' Andr ' , ' Jacques ' , ' Laure ' , ' Sophie ' , ' Victoire ']
>>> prenoms
[ ' Jacques ' , ' Laure ' , ' Andr ' , ' Victoire ' , ' Albert ' , ' Sophie ']
>>>

Vous devriez remarquer deux choses ici :


1. Dabord, Python a tri notre liste par ordre alphabtique. Nous verrons plus tard
pourquoi.
2. Le second moyen (avec la fonction sorted ) na pas modifi la liste, elle a juste
retourne une nouvelle liste trie. La mthode de liste sort, elle, a travaille sur
notre liste et la modifie.
214

TRIER AVEC DES CLS PRCISES

Aperu des critres de tri


Python a tri la liste par ordre alphabtique. . . mais nous ne lui avons rien demand
cet gard. En un sens, tant mieux, si cest ce que vous vouliez faire, mais il est
prfrable de comprendre pourquoi. Je vous met ici un petit code qui devrait vous
aider comprendre sur quelle information Python se fonde pour dterminer la meilleure
mthode de tri :
1
2
3
4
5

>>> sorted ([ 1 , 8 , -2 , 15 , 9 ])
[ -2 , 1 , 8 , 9 , 15 ]
>>> sorted ([ " 1 " , " 8 " , " -2 " , " 15 " , " 9 " ])
[ ' -2 ' , '1 ' , ' 15 ' , '8 ' , '9 ']
>>>

La rponse se trouve dans la diffrence entre la ligne 1 et la ligne 3. Vous avez trouv ?
Pour Python, la mthode de tri dpend du type des lments que la squence contient.
On lui a demand de trier une liste de nombres (type int) et Python trie du plus petit
au plus grand. Sans surprise.
la ligne 3 cependant, on lui demande de trier la mme liste, sauf que nos nombres
sont devenus des chanes de caractres (type str ). Python choisit donc de trier la liste
par ordre alphabtique.
Et si on a une liste contenant plusieurs types ?

Dans ce cas, Python va vous dire, sa faon, quil ne sait pas quelle mthode de tri
choisir.
1
2
3
4
5

>>> sorted ([ 1 , " 8 " , " -2 " , " 15 " , 9 ])


Traceback ( most recent call last ) :
File " < stdin > " , line 1 , in < module >
TypeError : unorderable types : str () < int ()
>>>

Notre liste contient des nombres (type int) et des chanes de caractre (type str ). Le
message derreur nest peut-tre pas trs explicite tant quon ne connat pas la faon
dont Python trie une squence, nous verrons a un peu plus loin dans le chapitre.
En attendant, intressons-nous des types plus particuliers !

Trier avec des cls prcises


Les deux moyens que nous venons de voir sont pratiques, mais limits. Si nous voulons
trier une liste contenant des donnes de types diffrents, selon des critres un peu plus
particuliers, on va avoir quelques problmes.
215

CHAPITRE 20. PARENTHSE SUR LE TRI EN PYTHON


Considrez cet exemple : on veut conserver, dans une liste simple, les tudiants, leur
ge et leur note moyenne (entre 0 et 20). On va commencer par crer une liste assez
simple, contenant des tuples. Pour chaque tuple, on indiquera le nom de ltudiant, son
ge et sa moyenne. Voyons le code :
1
2
3
4
5
6
7

etudiants = [
( " Cl ment " , 14 , 16 ) ,
( " Charles " , 12 , 15 ) ,
( " Oriane " , 14 , 18 ) ,
( " Thomas " , 11 , 12 ) ,
( " Damien " , 12 , 15 ) ,
]

Souvenez-vous : premire colonne, prnom, deuxime colonne, ge et troisime colonne,


moyenne entre 0 et 20.
Maintenant, si vous essayez de trier cette liste sans prciser de mthode :
1
2
3
4
5
6
7
8
9

>>> sorted ( etudiants )


[
( ' Charles ' , 12 , 15 ) ,
( ' Cl ment ' , 14 , 16 ) ,
( ' Damien ' , 12 , 15 ) ,
( ' Oriane ' , 14 , 18 ) ,
( ' Thomas ' , 11 , 12 )
]
>>>

La liste ne saffiche pas sous cette forme dans linterprteur par dfaut, jai
juste modifi le rsultat pour quil soit plus lisible.
Le plus important pour nous, cest que le tri semble seffectuer sur la premire colonne :
sur les prnoms. Lordre retourn est celui des tudiants par ordre alphabtique.
Maintenant, supposons que nous voulions trier par note.
Il suffit de changer les colonnes de notre liste, non ?

Oui, cest une solution et il sagit probablement de la solution laquelle on pense le


plus vite : changer les colonnes de notre liste, pour mettre les notes au dbut de notre
tuple, et aprs trier la liste.
Mais il y a plus simple !
216

TRIER AVEC DES CLS PRCISES

Largument key
La mthode list.sort ou la fonction sorted ont tous deux un paramtre optionnel, appel
key.
Cet argument attend. . . une fonction. Attendez ! Je mexplique.
La fonction passer en paramtre prend un lment de la liste et retourne ce sur quoi
doit seffectuer le tri.
Donc la premire chose est de crer une fonction ?

Oui, mais de faon assez simple : nous allons utiliser nos fonctions lambdas. Vous vous
en souvenez ? Je vous donne un petit exemple de code si besoin :
1
2
3
4
5
6

>>> doubler = lambda x : x * 2


>>> doubler
< function < lambda > at 0x00000000029AD1E0 >
>>> doubler ( 8 )
16
>>>

Les fonctions lambdas sont des fonctions particulires que lon peut crer grce au
mot cl lambda.
Sa syntaxe est la suivante :
1. Dabord, aprs le mot cl lambda, les arguments de la fonction crer, spars
par une virgule si il y en a plusieurs ;
2. Ensuite, les deux points ( :) ;
3. Et ensuite le retour de la fonction. Ici, on retourne le paramtre fois 2, tout
simplement.

Pourquoi ce rappel sur les lambdas ?

Parce que, pour trier, nous allons nous en servir. Pour prciser la mthode de tri, il
nous faut une fonction qui prenne en paramtre un lment de la liste trier et retourne
llment qui doit tre utilis pour trier.
Llment de notre liste etudiants, cest un tuple contenant le prnom, lge et la
moyenne de ltudiant ;
On veut trier le tableau des tudiants en fonction des notes (la troisime colonne du
tuple).
Est-ce que ces informations vous aident pour crer notre fonction lambda ?
La voici :
217

CHAPITRE 20. PARENTHSE SUR LE TRI EN PYTHON


lambda colonnes : colonnes [ 2 ]

colonnes contiendra un lment de la liste des tudiants (cest--dire un tuple). Si


on retourne colonnes[2], cela signifie quon veut rcuprer la moyenne de ltudiant
(troisime colonne). Souvenez-vous, pour un tuple, la premire colonne est toujours 0.
Essayons prsent de trier notre liste dtudiants en fonction de leur moyenne :
1
2
3
4
5
6
7
8
9

>>> sorted ( etudiants , key = lambda colonnes : colonnes [ 2 ])


[
( ' Thomas ' , 11 , 12 ) ,
( ' Charles ' , 12 , 15 ) ,
( ' Damien ' , 12 , 15 ) ,
( ' Cl ment ' , 14 , 16 ) ,
( ' Oriane ' , 14 , 18 )
]
>>>

Si le code ne vous parat pas clair, prenez le temps de relire les explications. Il faut un
peu de temps pour sadapter aux fonctions lambdas, mais vous verrez quelles sont
parfois trs utiles.

Trier une liste dobjets


Jusquici, nous avons tri des listes contenant des nombres ou chanes de caractres.
Ce sont des objets, bien entendu, mais maintenant je voudrais vous montrer comment
trier des objets issus de classes que nous avons cres.
Je vais reprendre le mme exemple de notre tableau dtudiants. Simplement, au lieu
de conserver des tuples, nous allons conserver des objets. Plus intuitif et plus lisible, je
trouve :
1

class Etudiant :

2
3

""" Classe repr sentant un tudiant .

4
5
6

On repr sente un tudiant par son pr nom ( attribut prenom ) ,


son ge
( attribut age ) et sa note moyenne ( attribut moyenne , entre
0 et 20 ) .

7
8
9
10
11

Param tres du constructeur :


prenom -- le pr nom de l ' tudiant
age -- l ' ge de l ' tudiant
moyenne -- la moyenne de l ' tudiant

12
13

"""

14
15
16
17

218

def __init__ ( self , prenom , age , moyenne ) :


self . prenom = prenom
self . age = age

TRIER AVEC DES CLS PRCISES


18

self . moyenne = moyenne

19
20
21
22

def __repr__ ( self ) :


return " < tudiant { } ( ge = { } , moyenne = { } ) >" . format (
self . prenom , self . age , self . moyenne )

Maintenant, recrons notre liste :


1
2
3
4
5
6
7

etudiants = [
Etudiant ( " Cl ment " , 14 , 16 ) ,
Etudiant ( " Charles " , 12 , 15 ) ,
Etudiant ( " Oriane " , 14 , 18 ) ,
Etudiant ( " Thomas " , 11 , 12 ) ,
Etudiant ( " Damien " , 12 , 15 ) ,
]

Si vous essayez de trier notre liste telle quelle, vous allez avoir une erreur qui devrait
vous sembler familire :
1
2
3
4
5
6
7
8
9
10
11
12
13

>>> etudiants
[
< tudiant Cl ment ( ge = 14 , moyenne = 16 ) >,
< tudiant Charles ( ge = 12 , moyenne = 15 ) >,
< tudiant Oriane ( ge = 14 , moyenne = 18 ) >,
< tudiant Thomas ( ge = 11 , moyenne = 12 ) >,
< tudiant Damien ( ge = 12 , moyenne = 15 ) >
]
>>> sorted ( etudiants )
Traceback ( most recent call last ) :
File " < stdin > " , line 1 , in < module >
TypeError : unorderable types : Etudiant () < Etudiant ()
>>>

Python ne sait pas comment trier nos tudiants. Il y a deux faons de le lui expliquer :
1. Lune est de dfinir la mthode spciale __lt__ de notre classe. Cest en effet
cette mthode (utilise pour la comparaison) qui est utilise par Python pour
trier une liste, en comparant chacun de ses lments. La mthode __lt__ (lower
than) correspond loprateur < ;
2. On peut aussi utiliser largument key, comme nous lavons fait prcdemment.
Ici notre seconde possibilit est plus pertinente. Redfinir la mthode __lt__ est une
bonne ide si notre objet est un nombre (par exemple une dure ou bien une heure).
Dans ce cas prcis, il est prfrable dutiliser largument key de la fonction sorted (ou
de la mthode list.sort).
Saurez-vous trier cette liste dtudiants en fonction de leur moyenne ?
Voici le code :
1
2

>>> sorted ( etudiants , key = lambda etudiant : etudiant . moyenne )


[

219

CHAPITRE 20. PARENTHSE SUR LE TRI EN PYTHON


3
4
5
6
7
8
9

]
>>>

< tudiant
< tudiant
< tudiant
< tudiant
< tudiant

Thomas ( ge = 11 , moyenne = 12 ) >,


Charles ( ge = 12 , moyenne = 15 ) >,
Damien ( ge = 12 , moyenne = 15 ) >,
Cl ment ( ge = 14 , moyenne = 16 ) >,
Oriane ( ge = 14 , moyenne = 18 ) >

On obtient la mme chose que dans notre exercice prcdent, quand nous utilisions des
tuples. Je trouve personnellement cette mthode plus lisible.

Trier dans lordre inverse


Il arrive souvent que lon veuille trier dans lordre inverse. Par exemple, que lon veuille
trier nos tudiants par ordre inverse dge (du plus grand au plus petit).
Une solution est de trier et ensuite dinverser la liste, mais l encore, il existe plus
rapide : largument reverse.
Cest un argument boolen que lon peut passer la mthode de liste sort ou la
fonction sorted.
Essayons par exemple de trier nos tudiants par ordre inverse dge :
1
2
3
4
5
6
7
8
9

>>> sorted ( etudiants , key = lambda etudiant : etudiant . age ,


reverse = True )
[
< tudiant Cl ment ( ge = 14 , moyenne = 16 ) >,
< tudiant Oriane ( ge = 14 , moyenne = 18 ) >,
< tudiant Charles ( ge = 12 , moyenne = 15 ) >,
< tudiant Damien ( ge = 12 , moyenne = 15 ) >,
< tudiant Thomas ( ge = 11 , moyenne = 12 ) >
]
>>>

Plutt simple, nest-ce pas ?

Plus rapide et plus efficace


Les mthodes de tri que nous avons vues jusquici sont trs pratiques. Leur plus grand
inconvnient est de reposer sur des fonctions lambdas. Il est vrai que dfinir une
lambda est rapide (et, une fois quon sest habitu la syntaxe, assez lisible). Par
contre les fonctions lambdas ne sont pas le meilleur choix au niveau rapidit, si vous
voulez trier une liste contenant beaucoup dobjets.
Mais tu as dit que le paramtre key attendait une fonction, ne peut-on dfinir
une fonction ordinaire ?
220

PLUS RAPIDE ET PLUS EFFICACE


Si si. Cest tout fait possible. Mais la plupart du temps, une des fonctions du module
operator que nous allons voir fait trs bien le travail.

Les fonctions du module operator


Le module operator propose plusieurs fonctions qui vont savrer utiles pour nous, dans
ce cas prcis. Nous allons nous intresser tout particulirement aux fonctions itemgetter
et attrgetter, mais sachez quil en existe dautres et que le module operator nest pas
uniquement utile pour le tri, loin sen faut.
Trier une liste de tuples
Dabord, voyons notre exemple avec les tuples :
1
2
3
4
5
6
7

etudiants = [
( " Cl ment " , 14 , 16 ) ,
( " Charles " , 12 , 15 ) ,
( " Oriane " , 14 , 18 ) ,
( " Thomas " , 11 , 12 ) ,
( " Damien " , 12 , 15 ) ,
]

Si on veut trier par moyenne ascendante, nous avons vu quil suffisait de faire :
1

sorted ( etudiants , key = lambda etudiant : etudiant [ 2 ])

Pour faire la mme chose sans fonction lambda, avec la fonction itemgetter du module
operator :
1
2

from operator import itemgetter


sorted ( etudiants , key = itemgetter ( 2 ) )

On appelle la fonction itemgetter avec le paramtre 2. Un objet operator.itemgetter est


cr et pass au paramtre key de la fonction sorted. Ensuite, pour chaque tudiant
contenu dans notre liste, lobjet operator.itemgetter est appel et retourne la note
moyenne de ltudiant.
Au final, on obtient le mme rsultat quavec notre fonction lambda, mais cette mthode est plus rapide sur un grand nombre de donnes et, une fois quon sest habitu
son aspect, plus facile lire.
Trier une liste dobjets
On peut faire la mme chose si on parcourt une liste dobjets, mais cette fois, on utilise
la fonction attrgetter. Je vous remet le code pour tre sr que vous avez le mme que
moi :
1

class Etudiant :

221

CHAPITRE 20. PARENTHSE SUR LE TRI EN PYTHON


""" Classe repr sentant un tudiant .

3
4

On repr sente un tudiant par son pr nom ( attribut prenom ) ,


son ge
( attribut age ) et sa note moyenne ( attribut moyenne , entre
0 et 20 ) .

5
6
7

Param tres du constructeur :


prenom -- le pr nom de l ' tudiant
age -- l ' ge de l ' tudiant
moyenne -- la moyenne de l ' tudiant

8
9
10
11
12

"""

13
14

def __init__ ( self , prenom , age , moyenne ) :


self . prenom = prenom
self . age = age
self . moyenne = moyenne

15
16
17
18
19

def __repr__ ( self ) :


return " < tudiant { } ( ge = { } , moyenne = { } ) >" . format (
self . prenom , self . age , self . moyenne )

20
21
22
23
24
25
26
27
28
29
30

etudiants = [
Etudiant ( " Cl ment " , 14 , 16 ) ,
Etudiant ( " Charles " , 12 , 15 ) ,
Etudiant ( " Oriane " , 14 , 18 ) ,
Etudiant ( " Thomas " , 11 , 12 ) ,
Etudiant ( " Damien " , 12 , 15 ) ,
]

Et maintenant pour trier notre liste dtudiants par note moyenne ascendante :
1
2

from operator import attrgetter


sorted ( etudiants , key = attrgetter ( " moyenne " ) )

Le systme est le mme, sauf que lon travaille ici sur une liste dobjets et que le calcul
est fait sur un attribut de lobjet (ici moyenne ) au lieu dun tuple.

Trier selon plusieurs critres


Trier selon un critre, cest dj trs bien, mais trier selon plusieurs critres, ce peut
tre encore mieux. Si nous voulons, disons, trier nos tudiants par ge et note moyenne.
Cest--dire que le tri se fera par ge, mais si deux tudiants ont le mme ge, le tri se
fera sur leur moyenne.
La bonne nouvelle ? Rien de nouveau : passez juste un nouveau paramtre la fonction
attrgetter :
1

222

>>> sorted ( etudiants , key = attrgetter ( " age " , " moyenne " ) )

PLUS RAPIDE ET PLUS EFFICACE


2

3
4
5
6
7
8
9

]
>>>

< tudiant
< tudiant
< tudiant
< tudiant
< tudiant

Thomas ( ge = 11 , moyenne = 12 ) >,


Charles ( ge = 12 , moyenne = 15 ) >,
Damien ( ge = 12 , moyenne = 15 ) >,
Cl ment ( ge = 14 , moyenne = 16 ) >,
Oriane ( ge = 14 , moyenne = 18 ) >

Vous avez peut-tre remarqu que lordre de Charles et Damien dans la liste est identique avant, mme si dautres tudiants ont chang de place : en effet, Charles et
Damien ont le mme ge et la mme moyenne et leur ordre nest pas modifi par
Python.
Cette proprit est appele stabilit . Si deux lments de la squence comparer
sont identiques, leur ordre est conserv.
Cette proprit du tri en Python permet de chaner nos tris.
Chanage de tris
Pour vous montrer un exemple concret, nous allons changer dobjets : nous allons
travailler sur un inventaire de produits avec leur prix et quantit vendues.
1

class LigneInventaire :

2
3

""" Classe repr sentant une ligne d ' un inventaire de vente .

4
5
6
7
8

Attributs attendus par le constructeur :


produit -- le nom du produit
prix -- le prix unitaire du produit
quantite -- la quantit vendue du produit .

9
10

"""

11
12
13
14
15

def __init__ ( self , produit , prix , quantite ) :


self . produit = produit
self . prix = prix
self . quantite = quantite

16
17
18
19

def __repr__ ( self ) :


return " < Ligne d ' inventaire { } ( { } X { } ) >" . format (
self . produit , self . prix , self . quantite )

20
21
22
23
24
25
26
27

# Cr ation de l ' inventaire


inventaire = [
LigneInventaire ( " pomme rouge " , 1 .2 , 19 ) ,
LigneInventaire ( " orange " , 1 .4 , 24 ) ,
LigneInventaire ( " banane " , 0 .9 , 21 ) ,
LigneInventaire ( " poire " , 1 .2 , 24 ) ,
]

223

CHAPITRE 20. PARENTHSE SUR LE TRI EN PYTHON


On veut trier cette liste par prix et par quantit. Facile, cest ce quon a fait un peu
plus haut :
1
2

from operator import attrgetter


sorted ( inventaire , key = attrgetter ( " prix " , " quantite " ) )

Ce qui vous renvoie :


1

2
3
4
5
6

< Ligne
< Ligne
< Ligne
< Ligne

d ' inventaire
d ' inventaire
d ' inventaire
d ' inventaire

banane ( 0 . 9X21 ) >,


pomme rouge ( 1 . 2X19 ) >,
poire ( 1 . 2X24 ) >,
orange ( 1 . 4X24 ) >

Mais si vous voulez trier par prix croissant et par quantit dcroissante ? Cest--dire
quon veut trier par prix croissant, mais que si deux lignes dinventaires ont le mme
prix, alors on trie dans lordre dcroissant de quantit ?
Le plus simple ici est de faire deux tris en utilisant la proprit de stabilit. La subtilit,
cest que lon va trier dabord par notre second critre et ensuite par notre premier.
Ici, nous allons donc trier dabord par ordre dcroissant de quantit, puis ensuite par
ordre croissant de prix.
Si vous vous demandez pourquoi, faites plusieurs essais (dans lordre que jai indiqu
et dans lordre inverse). Si cela vous aide, essayez dcrire linventaire sur une feuille et
de trier dans un ordre et dans lautre.
Voici le code pour notre tri. Dabord par quantit, ensuite par prix :
inventaire . sort ( key = attrgetter ( " quantite " ) , reverse = True )
sorted ( inventaire , key = attrgetter ( " prix " ) )

1
2

Et vous devriez obtenir :


1

2
3
4
5
6

< Ligne
< Ligne
< Ligne
< Ligne

d ' inventaire
d ' inventaire
d ' inventaire
d ' inventaire

banane ( 0 . 9X21 ) >,


poire ( 1 . 2X24 ) >,
pomme rouge ( 1 . 2X19 ) >,
orange ( 1 . 4X24 ) >

On utilise ici la mthode de liste sort comme on aurait pu utiliser la fonction sorted.
Regardez surtout lordre dans lequel la poire et la pomme rouge apparaissent : les deux
lignes dinventaire ont le mme prix, mais puisque la poire a t vendue en plus grande
quantit, elle apparat en premier. Ceci naurait pas t possible sans la stabilit dans
le tri.
Sans cette proprit, le second tri (par prix) aurait compltement modifi lordre de
notre liste, rendant inutile notre premier tri (par quantit inverse).
Voil pour ce tour dhorizon des mthodes de tri proposes par Python. Sachez que
vous pourrez retrouver les fonctions cls (souvent en paramtre key dune fonction)
pour dautres usages que le tri.
224

PLUS RAPIDE ET PLUS EFFICACE

En rsum
Le tri en Python se fait grce la mthode de liste sort, qui modifie la liste dorigine,
et la fonction sorted, qui ne modifie pas la liste (ou la squence) passe en paramtre ;
On peut spcifier des fonctions cls grce largument key. Ces fonctions sont appeles pour chaque lment de la squence trier, et retournent le critre du tri ;
Le module operator propose les fonctions itemgetter et attrgetter qui peuvent tre
trs utiles en tant que fonction cls, si on veut trier une liste de tuples ou une liste
dobjets selon un attribut ;
Le tri en Python est stable , cest--dire que lordre de deux lments dans la liste
nest pas modifi sils sont gaux. Cette proprit permet le chanage de tri.

225

CHAPITRE 20. PARENTHSE SUR LE TRI EN PYTHON

226

Chapitre

21

Lhritage
Difficult :
entends souvent dire quun langage de programmation orient objet nincluant pas
lhritage serait incomplet, sinon inutile. Aprs avoir dcouvert par moi-mme cette
fonctionnalit et les techniques qui en dcoulent, je suis forc de reconnatre que sans
lhritage, le monde serait moins beau !

Quest-ce que cette fonctionnalit a de si utile ? Nous allons le voir, bien entendu. Et je
vais surtout essayer de vous montrer des exemples dapplications. Car trs souvent, quand
on dcouvre lhritage, on ne sait pas trop quoi en faire. . . Ne vous attendez donc pas un
chapitre o vous nallez faire que coder. Vous allez devoir vous pencher sur de la thorie
et travailler sur quelques exemples de modlisation. Mais je vous guide, ne vous inquitez
pas !

227

CHAPITRE 21. LHRITAGE

Pour bien commencer


Je ne vais pas faire durer le suspense plus longtemps : lhritage est une fonctionnalit
objet qui permet de dclarer que telle classe sera elle-mme modele sur une autre
classe, quon appelle la classe parente, ou la classe mre. Concrtement, si une classe
b hrite de la classe a, les objets crs sur le modle de la classe b auront accs aux
mthodes et attributs de la classe a.
Et cest tout ? Cela ne sert rien !

Non, ce nest pas tout, et si, cela sert normment mais vous allez devoir me laisser un
peu de temps pour vous en montrer lintrt.
La premire chose, cest que la classe b dans notre exemple ne se contente pas de
reprendre les mthodes et attributs de la classe a : elle va pouvoir en dfinir dautres.
Dautres mthodes et dautres attributs qui lui seront propres, en plus des mthodes
et attributs de la classe a. Et elle va pouvoir galement redfinir les mthodes de la
classe mre.
Prenons un exemple simple : on a une classe Animal permettant de dfinir des animaux.
Les animaux tels que nous les modlisons ont certains attributs (le rgime : carnivore
ou herbivore) et certaines mthodes (manger, boire, crier. . .).
On peut maintenant dfinir une classe Chien qui hrite de Animal, cest--dire quelle
reprend ses mthodes. Nous allons voir plus bas ce que cela implique exactement.
Si vous ne voyez pas trs bien dans quel cas on fait hriter une classe dune autre, faites
le test :
on fait hriter la classe Chien de Animal parce quun chien est un animal ;
on ne fait pas hriter Animal de Chien parce quAnimal nest pas un Chien.
Sur ce modle, vous pouvez vous rendre compte quune voiture est un vhicule. La
classe Voiture pourrait donc hriter de Vehicule.
Intressons-nous prsent au code.

Lhritage simple
On oppose lhritage simple, dont nous venons de voir les aspects thoriques dans la
section prcdente, lhritage multiple que nous verrons dans la prochaine section.
Il est temps daborder la syntaxe de lhritage. Nous allons dfinir une premire classe
A et une seconde classe B qui hrite de A.
1
2
3
4

228

class A :
""" Classe A , pour illustrer notre exemple d 'h ritage """
pass # On laisse la d finition vide , ce n ' est qu ' un exemple

LHRITAGE SIMPLE
5
6
7
8

class B ( A ) :
""" Classe B ,
Elle reprend
exemple ,
A ne poss de

qui h rite de A .
les m mes m thodes et attributs ( dans cet
la classe
de toute fa on ni m thode ni attribut ) """

9
10

pass

Vous pourrez exprimenter par la suite sur des exemples plus constructifs. Pour linstant, limportant est de bien noter la syntaxe qui, comme vous le voyez, est des plus
simples : class MaClasse(MaClasseMere):. Dans la dfinition de la classe, entre le
nom et les deux points, vous prcisez entre parenthses la classe dont elle doit hriter. Comme je lai dit, dans un premier temps, toutes les mthodes de la classe A se
retrouveront dans la classe B.
Jai essay de mettre des constructeurs dans les deux classes mais, dans la
classe fille, je ne retrouve pas les attributs dclars dans ma classe mre, cest
normal ?
Tout fait. Vous vous souvenez quand je vous ai dit que les mthodes taient dfinies
dans la classe, alors que les attributs taient directement dclars dans linstance dobjet ? Vous le voyez bien de toute faon : cest dans le constructeur quon dclare les
attributs et on les crit tous dans linstance self.
Quand une classe B hrite dune classe A, les objets de type B reprennent bel et bien
les mthodes de la classe A en mme temps que celles de la classe B. Mais, assez
logiquement, ce sont celles de la classe B qui sont appeles dabord.
Si vous faites objet_de_type_b.ma_methode(), Python va dabord chercher la mthode ma_methode dans la classe B dont lobjet est directement issu. Sil ne trouve pas,
il va chercher rcursivement dans les classes dont hrite B, cest--dire A dans notre
exemple. Ce mcanisme est trs important : il induit que si aucune mthode na t
redfinie dans la classe, on cherche dans la classe mre. On peut ainsi redfinir une
certaine mthode dans une classe et laisser dautres directement hriter de la classe
mre.
Petit code dexemple :
1
2
3
4
5
6
7
8
9

class Personne :
""" Classe repr sentant une personne """
def __init__ ( self , nom ) :
""" Constructeur de notre classe """
self . nom = nom
self . prenom = " Martin "
def __str__ ( self ) :
""" M thode appel e lors d ' une conversion de l ' objet en
cha ne """
return " { 0 } { 1 } " . format ( self . prenom , self . nom )

10
11

class AgentSpecial ( Personne ) :

229

CHAPITRE 21. LHRITAGE


""" Classe d finissant un agent sp cial .
Elle h rite de la classe Personne """

12
13
14

def __init__ ( self , nom , matricule ) :


""" Un agent se d finit par son nom et son matricule """
self . nom = nom
self . matricule = matricule
def __str__ ( self ) :
""" M thode appel e lors d ' une conversion de l ' objet en
cha ne """
return " Agent { 0 } , matricule { 1 } " . format ( self . nom , self
. matricule )

15
16
17
18
19
20
21

Vous voyez ici un exemple dhritage simple. Seulement, si vous essayez de crer des
agents spciaux, vous risquez davoir de drles de surprises :
1
2
3
4
5
6
7
8
9
10

>>> agent = AgentSpecial (" Fisher " , "18327 -121")


>>> agent . nom
Fisher
>>> print ( agent )
Agent Fisher , matricule 18327 -121
>>> agent . prenom
Traceback ( most recent call last ) :
File " < stdin >" , line 1 , in < module >
AttributeError : AgentSpecial object has no attribute prenom
>>>

Argh. . . mais tu navais pas dit quune classe reprenait les mthodes et attributs de sa classe mre ?
Si. Mais en suivant bien lexcution, vous allez comprendre : tout commence la cration de lobjet. Quel constructeur appeler ? Sil ny avait pas de constructeur dfini dans
notre classe AgentSpecial, Python appellerait celui de Personne. Mais il en existe bel
et bien un dans la classe AgentSpecial et cest donc celui-ci qui est appel. Dans ce
constructeur, on dfinit deux attributs, nom et matricule. Mais cest tout : le constructeur de la classe Personne nest pas appel, sauf si vous lappelez explicitement dans
le constructeur dAgentSpecial.
Dans le premier chapitre, je vous ai expliqu que mon_objet.ma_methode() revenait
au mme que MaClasse.ma_methode(mon_objet). Dans notre mthode ma_methode, le
premier paramtre self sera mon_objet. Nous allons nous servir de cette quivalence.
La plupart du temps, crire mon_objet.ma_methode() suffit. Mais dans une relation
dhritage, il peut y avoir, comme nous lavons vu, plusieurs mthodes du mme nom
dfinies dans diffrentes classes. Laquelle appeler ? Python choisit, sil la trouve, celle
dfinie directement dans la classe dont est issu lobjet, et sinon parcourt la hirarchie
de lhritage jusqu tomber sur la mthode. Mais on peut aussi se servir de la notation
MaClasse.ma_methode(mon_objet) pour appeler une mthode prcise dune classe
230

LHRITAGE SIMPLE
prcise. Et cela est utile dans notre cas :
1
2
3
4
5
6
7
8
9

class Personne :
""" Classe repr sentant une personne """
def __init__ ( self , nom ) :
""" Constructeur de notre classe """
self . nom = nom
self . prenom = " Martin "
def __str__ ( self ) :
""" M thode appel e lors d ' une conversion de l ' objet en
cha ne """
return " { 0 } { 1 } " . format ( self . prenom , self . nom )

10
11
12
13

class AgentSpecial ( Personne ) :


""" Classe d finissant un agent sp cial .
Elle h rite de la classe Personne """

14
15
16
17
18
19
20
21
22

def __init__ ( self , nom , matricule ) :


""" Un agent se d finit par son nom et son matricule """
# On appelle explicitement le constructeur de Personne
:
Personne . __init__ ( self , nom )
self . matricule = matricule
def __str__ ( self ) :
""" M thode appel e lors d ' une conversion de l ' objet en
cha ne """
return " Agent { 0 } , matricule { 1 } " . format ( self . nom , self
. matricule )

Si cela vous parat encore un peu vague, exprimentez : cest toujours le meilleur moyen.
Entranez-vous, contrlez lcriture des attributs, ou revenez au premier chapitre de
cette partie pour vous rafrachir la mmoire au sujet du paramtre self, bien qu
force de manipulations vous avez d comprendre lide.
Reprenons notre code de tout lheure qui, cette fois, passe sans problme :
1
2
3
4
5
6
7
8

>>> agent = AgentSpecial (" Fisher " , "18327 -121")


>>> agent . nom
Fisher
>>> print ( agent )
Agent Fisher , matricule 18327 -121
>>> agent . prenom
Martin
>>>

Cette fois, notre attribut prenom se trouve bien dans notre agent spcial car le constructeur de la classe AgentSpecial appelle explicitement celui de Personne.
Vous pouvez noter galement que, dans le constructeur dAgentSpecial, on ninstancie
pas lattribut nom. Celui-ci est en effet crit par le constructeur de la classe Personne
que nous appelons en lui passant en paramtre le nom de notre agent.
231

CHAPITRE 21. LHRITAGE


Notez que lon pourrait trs bien faire hriter une nouvelle classe de notre classe
Personne, la classe mre est souvent un modle pour plusieurs classes filles.

Petite prcision
Dans le chapitre prcdent, je suis pass trs rapidement sur lhritage, ne voulant pas
trop my attarder et brouiller les cartes inutilement. Mais jai expliqu brivement que
toutes les classes que vous crez hritent de la classe object. Cest elle, notamment,
qui dfinit toutes les mthodes spciales que nous avons vues au chapitre prcdent et
qui connat, bien mieux que nous, le mcanisme interne de lobjet. Vous devriez un peu
mieux, prsent, comprendre le code du chapitre prcdent. Le voici, en substance :
1
2
3
4

def __setattr__ ( self , nom_attribut , valeur_attribut ) :


""" M thode appel e quand on fait objet . attribut =
valeur """
print ( " Attention , on modifie l ' attribut { 0 } de l ' objet
! " . format ( nom_attribut ) )
object . __setattr__ ( self , nom_attribut , valeur_attribut )

En redfinissant la mthode __setattr__, on ne peut, dans le corps de cette mthode,


modifier les valeurs de nos attributs comme on le fait habituellement (self.attribut =
valeur) car alors, la mthode sappellerait elle-mme. On fait donc appel la mthode
__setattr__ de la classe object, cette classe dont hritent implicitement toutes nos
classes. On est sr que la mthode de cette classe sait crire une valeur dans un attribut,
alors que nous ignorons le mcanisme et que nous navons pas besoin de le connatre :
cest la magie du procd, une fois quon a bien compris le principe !

Deux fonctions trs pratiques


Python dfinit deux fonctions qui peuvent se rvler utiles dans bien des cas : issubclass
et isinstance.
issubclass
Comme son nom lindique, elle vrifie si une classe est une sous-classe dune autre
classe. Elle renvoie True si cest le cas, False sinon :
1
2
3
4
5
6
7
8

>>> issubclass ( AgentSpecial , Personne ) # AgentSpecial h rite de


Personne
True
>>> issubclass ( AgentSpecial , object )
True
>>> issubclass ( Personne , object )
True
>>> issubclass ( Personne , AgentSpecial ) # Personne n h rite pas
d AgentSpecial
False

232

LHRITAGE MULTIPLE
9

>>>

isinstance
isinstance permet de savoir si un objet est issu dune classe ou de ses classes filles :
1
2
3
4
5
6

>>> agent = AgentSpecial (" Fisher " , "18327 -121")


>>> isinstance ( agent , AgentSpecial ) # Agent est une instance d
AgentSpecial
True
>>> isinstance ( agent , Personne ) # Agent est une instance h rit
e de Personne
True
>>>

Ces quelques exemples suffisent, je pense. Peut-tre devrez-vous attendre un peu avant
de trouver une utilit ces deux fonctions mais ce moment viendra.

Lhritage multiple
Python inclut un mcanisme permettant lhritage multiple. Lide est en substance
trs simple : au lieu dhriter dune seule classe, on peut hriter de plusieurs.
Ce nest pas ce qui se passe quand on hrite dune classe qui hrite elle-mme
dune autre classe ?
Pas tout fait. La hirarchie de lhritage simple permet dtendre des mthodes et
attributs dune classe plusieurs autres, mais la structure reste ferme. Pour mieux
comprendre, considrez lexemple qui suit.
On peut sasseoir dans un fauteuil. On peut dormir dans un lit. Mais on peut sasseoir et
dormir dans certains canaps (la plupart en fait, avec un peu de bonne volont). Notre
classe Fauteuil pourra hriter de la classe ObjetPourSAsseoir et notre classe Lit, de
notre classe ObjetPourDormir. Mais notre classe Canape alors ? Elle devra logiquement
hriter de nos deux classes ObjetPourSAsseoir et ObjetPourDormir. Cest un cas o
lhritage multiple pourrait se rvler utile.
Assez souvent, on utilisera lhritage multiple pour des classes qui ont besoin de certaines fonctionnalits dfinies dans une classe mre. Par exemple, une classe peut produire des objets destins tre enregistrs dans des fichiers. On peut faire hriter de
cette classe toutes celles qui produiront des objets enregistrer dans des fichiers. Mais
ces mmes classes pourront hriter dautres classes incluant, pourquoi pas, dautres
fonctionnalits.
Cest une des utilisations de lhritage multiple et il en existe dautres. Bien souvent,
lutilisation de cette fonctionnalit ne vous semblera vidente quen vous penchant sur
233

CHAPITRE 21. LHRITAGE


la hirarchie dhritage de votre programme. Pour linstant, je vais me contenter de
vous donner la syntaxe et un peu de thorie supplmentaire, en vous encourageant
essayer par vous-mmes :
class MaClasseHeritee ( MaClasseMere1 , MaClasseMere2 ) :

Vous pouvez faire hriter votre classe de plus de deux autres classes. Au lieu de prciser,
comme dans les cas dhritage simple, une seule classe mre entre parenthses, vous en
indiquez plusieurs, spares par des virgules.

Recherche des mthodes


La recherche des mthodes se fait dans lordre de la dfinition de la classe. Dans
lexemple ci-dessus, si on appelle une mthode dun objet issu de MaClasseHeritee, on
va dabord chercher dans la classe MaClasseHeritee. Si la mthode nest pas trouve,
on la cherche dabord dans MaClasseMere1. Encore une fois, si la mthode nest pas
trouve, on cherche dans toutes les classes mres de la classe MaClasseMere1, si elle en
a, et selon le mme systme. Si, encore et toujours, on ne trouve pas la mthode, on la
recherche dans MaClasseMere2 et ses classes mres successives.
Cest donc lordre de dfinition des classes mres qui importe. On va chercher la mthode dans les classes mres de gauche droite. Si on ne trouve pas la mthode dans
une classe mre donne, on remonte dans ses classes mres, et ainsi de suite.

Retour sur les exceptions


Depuis la premire partie, nous ne sommes pas revenus sur les exceptions. Toutefois,
ce chapitre me donne une opportunit daller un peu plus loin.
Les exceptions sont non seulement des classes, mais des classes hirarchises selon une
relation dhritage prcise.
Cette relation dhritage devient importante quand vous utilisez le mot-cl except. En
effet, le type de lexception que vous prcisez aprs est intercept. . . ainsi que toutes
les classes qui hritent de ce type.
Mais comment fait-on pour savoir quune exception hrite dautres exceptions ?
Il y a plusieurs possibilits. Si vous vous intressez une exception en particulier,
consultez laide qui lui est lie.
1

Help on class AttributeError in module builtins :

2
3
4

234

class AttributeError ( Exception )


| Attribute not found .

RETOUR SUR LES EXCEPTIONS


5
6
7
8
9
10

|
|
|
|
|
|

Method resolution order :


AttributeError
Exception
BaseException
object

Vous apprenez ici que lexception AttributeError hrite de Exception, qui hrite
elle-mme de BaseException.
Vous pouvez galement retrouver la hirarchie des exceptions built-in sur le site de
Python, via ce code web :


Hirarchie des exceptions
B
Code web : 360446


Ne sont rpertories ici que les exceptions dites built-in. Dautres peuvent tre dfinies
dans des modules que vous utiliserez et vous pouvez mme en crer vous-mmes (nous
allons voir cela un peu plus bas).
Pour linstant, souvenez-vous que, quand vous crivez except TypeException, vous
pourrez intercepter toutes les exceptions du type TypeException mais aussi celles des
classes hrites de TypeException.
La plupart des exceptions sont leves pour signaler une erreur. . . mais pas toutes.
Lexception KeyboardInterupt
est leve quand vous interrompez votre programme,


par exemple avec CTRL + C . Si bien que, quand on souhaite intercepter toutes les
erreurs potentielles, on vitera dcrire un simple except: et on le remplacera par
except Exception:, toutes les exceptions derreurs tant drives de Exception.

Cration dexceptions personnalises


Il peut vous tre utile de crer vos propres exceptions. Puisque les exceptions sont des
classes, comme nous venons de le voir, rien ne vous empche de crer les vtres. Vous
pourrez les lever avec raise, les intercepter avec except.
Se positionner dans la hirarchie
Vos exceptions doivent hriter dune exception built-in propose par Python. Commencez par parcourir la hirarchie des exceptions built-in pour voir si votre exception peut
tre drive dune exception qui lui serait proche. La plupart du temps, vous devrez
choisir entre ces deux exceptions :
BaseException : la classe mre de toutes les exceptions. La plupart du temps, si vous
faites hriter votre classe de BaseException, ce sera pour modliser une exception qui
ne sera pas foncirement une erreur, par exemple une interruption dans le traitement
de votre programme.
Exception : cest de cette classe que vos exceptions hriteront la plupart du temps.
Cest la classe mre de toutes les exceptions derreurs .
235

CHAPITRE 21. LHRITAGE


Si vous pouvez trouver, dans le contexte, une exception qui se trouve plus bas dans la
hirarchie, cest toujours mieux.
Que doit contenir notre classe exception ?

Deux choses : un constructeur et une mthode __str__ car, au moment o lexception


est leve, elle doit tre affiche. Souvent, votre constructeur ne prend en paramtre que
le message derreur et la mthode __str__ renvoie ce message :
1
2
3
4
5
6
7
8

class MonException ( Exception ) :


""" Exception lev e dans un certain contexte... qui reste d
finir """
def __init__ ( self , message ) :
""" On se contente de stocker le message d ' erreur """
self . message = message
def __str__ ( self ) :
""" On renvoie le message """
return self . message

Cette exception sutilise le plus simplement du monde :


1
2
3
4
5

>>> raise MonException (" OUPS ... j ai tout cass ")


Traceback ( most recent call last ) :
File " < stdin >" , line 1 , in < module >
__main__ . MonException : OUPS ... j ai tout cass
>>>

Mais vos exceptions peuvent aussi prendre plusieurs paramtres linstanciation :


1
2
3

class E r r eurAnalyseFichier ( Exception ) :


""" Cette exception est lev e quand un fichier ( de
configuration )
n 'a pas pu tre analys .

4
5
6
7
8

Attributs :
fichier -- le nom du fichier posant probl me
ligne -- le num ro de la ligne posant probl me
message -- le probl me proprement dit """

9
10
11
12
13
14
15
16
17
18

236

def __init__ ( self , fichier , ligne , message ) :


""" Constructeur de notre exception """
self . fichier = fichier
self . ligne = ligne
self . message = message
def __str__ ( self ) :
""" Affichage de l ' exception """
return " [ { } : { } ]: { } " . format ( self . fichier , self . ligne , \
self . message )

RETOUR SUR LES EXCEPTIONS


Et pour lever cette exception :
1
2
3
4
5
6

>>> raise E r reurAnalyseFichier (" plop . conf " , 34 ,


...
" Il manque une parenth se la fin de l expression
")
Traceback ( most recent call last ) :
File " < stdin >" , line 2 , in < module >
__main__ . E r r e urAnalyseFichier : [ plop . conf :34]: il manque une
parenth se la fin de l expression
>>>

Voil, ce petit retour sur les exceptions est achev. Si vous voulez en savoir plus,
nhsitez pas consulter la documentation Python les concernant, accessible grce aux
codes web suivants :


Les exceptions
B
Code web : 777269




Les exceptions personnalises
B
Code web : 114349

En rsum
Lhritage permet une classe dhriter du comportement dune autre en reprenant
ses mthodes.
La syntaxe de lhritage est class NouvelleClasse(ClasseMere):.
On peut accder aux mthodes de la classe mre directement via la syntaxe :
ClasseMere.methode(self).
Lhritage multiple permet une classe dhriter de plusieurs classes mres.
La syntaxe de lhritage multiple scrit donc de la manire suivante :
class NouvelleClasse(ClasseMere1, ClasseMere2, ClasseMereN):.
Les exceptions dfinies par Python sont ordonnes selon une hirarchie dhritage.

237

CHAPITRE 21. LHRITAGE

238

Chapitre

22

Derrire la boucle for


Difficult :

oil pas mal de chapitres, nous avons tudi les boucles. Ne vous alarmez pas, ce
que nous avons vu est toujours dactualit . . . mais nous allons un peu approfondir le
sujet, maintenant que nous explorons le monde de lobjet.

Nous allons ici parler ditrateurs et de gnrateurs. Nous allons dcouvrir ces concepts du
plus simple au plus complexe et de telle sorte que chacun des concepts abords reprenne les
prcdents. Nhsitez pas, par la suite, revenir sur ce chapitre et le relire, partiellement
ou intgralement si ncessaire.

239

CHAPITRE 22. DERRIRE LA BOUCLE FOR

Les itrateurs
Nous utilisons des itrateurs sans le savoir depuis le moment o nous avons abord les
boucles et surtout, depuis que nous utilisons le mot-cl for pour parcourir des objets
conteneurs.
1
2

ma_liste = [1 , 2 , 3 ]
for element in ma_liste :

Utiliser les itrateurs


Cest sur la seconde ligne que nous allons nous attarder : force dutiliser ce type de
syntaxe, vous avez d vous y habituer et ce type de parcours doit vous tre familier.
Mais il se cache bel et bien un mcanisme derrire cette instruction.
Quand Python tombe sur une ligne du type for element in ma_liste:, il va appeler
litrateur de ma_liste. Litrateur, cest un objet qui va tre charg de parcourir
lobjet conteneur, ici une liste.
Litrateur est cr dans la mthode spciale __iter__ de lobjet. Ici, cest donc la mthode __iter__ de la classe list qui est appele et qui renvoie un itrateur permettant
de parcourir la liste.
chaque tour de boucle, Python appelle la mthode spciale __next__ de litrateur,
qui doit renvoyer llment suivant du parcours ou lever lexception StopIteration si
le parcours touche sa fin.
Ce nest peut-tre pas trs clair. . . alors voyons un exemple.
Avant de plonger dans le code, sachez que Python utilise deux fonctions pour appeler
et manipuler les itrateurs : iter permet dappeler la mthode spciale __iter__ de
lobjet pass en paramtre et next appelle la mthode spciale __next__ de litrateur
pass en paramtre.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

>>> ma_chaine = " test "


>>> i t e r a t eur _de _m a_c ha ine = iter ( ma_chaine )
>>> i t e r a t eur _de _m a_c ha ine
< str_iterator object at 0 x00B408F0 >
>>> next ( it er ate ur_ de _ma _c hai ne )
t
>>> next ( it er ate ur_ de _ma _c hai ne )
e
>>> next ( it er ate ur_ de _ma _c hai ne )
s
>>> next ( it er ate ur_ de _ma _c hai ne )
t
>>> next ( it er ate ur_ de _ma _c hai ne )
Traceback ( most recent call last ) :
File " < stdin >" , line 1 , in < module >
StopIteration

240

LES ITRATEURS
17

>>>

On commence par crer une chane de caractres (jusque l, rien de compliqu).


On appelle ensuite la fonction iter en lui passant en paramtre la chane. Cette
fonction appelle la mthode spciale __iter__ de la chane, qui renvoie litrateur
permettant de parcourir ma_chaine.
On va ensuite appeler plusieurs fois la fonction next en lui passant en paramtre
litrateur. Cette fonction appelle la mthode spciale __next__ de litrateur. Elle
renvoie successivement chaque lettre contenue dans notre chane et lve une exception
StopIteration quand la chane a t parcourue entirement.
Quand on parcourt une chane grce une boucle for (for lettre in chaine:), cest
ce mcanisme ditrateur qui est appel. Chaque lettre renvoye par notre itrateur se
retrouve dans la variable lettre et la boucle sarrte quand lexception StopIteration
est leve.
Vous pouvez reprendre ce code avec dautres objets conteneurs, des listes par exemple.

Crons nos itrateurs


Pour notre exemple, nous allons crer deux classes :
RevStr : une classe hritant de str qui se contentera de redfinir la mthode __iter__.
Son mode de parcours sera ainsi altr : au lieu de parcourir la chane de gauche
droite, on la parcourra de droite gauche (de la dernire lettre la premire).
ItRevStr : notre itrateur. Il sera cr depuis la mthode __iter__ de RevStr et
devra parcourir notre chane du dernier caractre au premier.
Ce mcanisme est un peu nouveau, je vous mets le code sans trop de suspense. Si
vous vous sentez de faire lexercice, nhsitez pas, mais je vous donnerai de toute faon
loccasion de pratiquer ds le prochain chapitre.
1
2
3
4
5

class RevStr ( str ) :


""" Classe reprenant les m thodes et attributs des cha nes
construites
depuis ' str '. On se contente de d finir une m thode de
parcours
diff rente : au lieu de parcourir la cha ne de la premi re
la derni re
lettre , on la parcourt de la derni re la premi re .

6
7
8

Les autres m thodes , y compris le constructeur , n ' ont pas


besoin
d ' tre red finies """

9
10
11
12

def __iter__ ( self ) :


""" Cette m thode renvoie un it rateur parcourant la cha
ne
dans le sens inverse de celui de ' str ' """

13

241

CHAPITRE 22. DERRIRE LA BOUCLE FOR


return ItRevStr ( self ) # On renvoie l ' it rateur cr
pour l ' occasion

14
15

class ItRevStr :
""" Un it rateur permettant de parcourir une cha ne de la
derni re lettre
la premi re . On stocke dans des attributs la position
courante et la
cha ne parcourir """

16
17
18
19
20

def __init__ ( self , chaine_a_parcourir ) :


""" On se positionne la fin de la cha ne """
self . chaine_a_parcourir = chaine_a_parcourir
self . position = len ( chaine_a_parcourir )
def __next__ ( self ) :
""" Cette m thode doit renvoyer l ' l ment suivant dans
le parcours ,
ou lever l ' exception ' StopIteration ' si le parcours est
fini """

21
22
23
24
25
26
27
28

if self . position == 0 : # Fin du parcours


raise StopIteration
self . position -= 1 # On d cr mente la position
return self . chaine_a_parcourir [ self . position ]

29
30
31
32

prsent, vous pouvez crer des chanes devant se parcourir du dernier caractre vers
le premier.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

>>> ma_chaine = RevStr (" Bonjour ")


>>> ma_chaine
Bonjour
>>> for lettre in ma_chaine :
...
print ( lettre )
...
r
u
o
j
n
o
B
>>>

Sachez quil est aussi possible de mettre en uvre directement la mthode __next__
dans notre objet conteneur. Dans ce cas, la mthode __iter__ pourra renvoyer self.
Vous pouvez voir un exemple, dont le code ci-dessus est inspir, en utilisant le code
web suivant :


Exemple sur les itrateurs
B
Code web : 547173


242

LES GNRATEURS
Cela reste quand mme plutt lourd non, de devoir faire des itrateurs
chaque fois ? Surtout si nos objets conteneurs doivent se parcourir de plusieurs
faons, comme les dictionnaires par exemple.
Oui, il subsiste quand mme beaucoup de rptitions dans le code que nous devons
produire, surtout si nous devons crer plusieurs itrateurs pour un mme objet. Souvent,
on utilisera des itrateurs existants, par exemple celui des listes. Mais il existe aussi un
autre mcanisme, plus simple et plus intuitif : la raison pour laquelle je ne vous montre
pas en premier cette autre faon de faire, cest que cette autre faon passe quand mme
par des itrateurs, mme si cest implicite, et quil nest pas mauvais de savoir comment
cela marche en coulisse.
Il est temps prsent de jeter un coup dil du ct des gnrateurs.

Les gnrateurs
Les gnrateurs sont avant tout un moyen plus pratique de crer et manipuler des
itrateurs. Vous verrez un peu plus loin dans ce chapitre quils permettent des choses
assez complexes, mais leur puissance tient surtout leur simplicit et leur petite taille.

Les gnrateurs simples


Pour crer des gnrateurs, nous allons dcouvrir un nouveau mot-cl : yield. Ce motcl ne peut sutiliser que dans le corps dune fonction et il est suivi dune valeur
renvoyer.

Attends un peu. . . une valeur ? renvoyer ?

Oui. Le principe des gnrateurs tant un peu particulier, il ncessite un mot-cl pour
lui tout seul. Lide consiste dfinir une fonction pour un type de parcours. Quand
on demande le premier lment du parcours (grce next), la fonction commence son
excution. Ds quelle rencontre une instruction yield, elle renvoie la valeur qui suit et
se met en pause. Quand on demande llment suivant de lobjet (grce, une nouvelle
fois, next), lexcution reprend lendroit o elle stait arrte et sinterrompt au
yield suivant. . . et ainsi de suite. la fin de lexcution de la fonction, lexception
StopIteration est automatiquement leve par Python.
Nous allons prendre un exemple trs simple pour commencer :
1
2
3
4

>>> def mon_generateur () :


...
""" Notre premier g n rateur . Il va simplement renvoyer
1 , 2 et 3"""
...
yield 1
...
yield 2

243

CHAPITRE 22. DERRIRE LA BOUCLE FOR


5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

...
yield 3
...
>>> mon_generateur
< function mon_generateur at 0 x00B494F8 >
>>> mon_generateur ()
< generator object mon_generateur at 0 x00B9DC88 >
>>> mon_iterateur = iter ( mon_generateur () )
>>> next ( mon_iterateur )
1
>>> next ( mon_iterateur )
2
>>> next ( mon_iterateur )
3
>>> next ( mon_iterateur )
Traceback ( most recent call last ) :
File " < stdin >" , line 1 , in < module >
StopIteration
>>>

Je pense que cela vous rappelle quelque chose ! Cette fonction, part lutilisation de
yield, est plutt classique. Quand on lexcute, on se retrouve avec un gnrateur.
Ce gnrateur est un objet cr par Python qui dfinit sa propre mthode spciale
__iter__ et donc son propre itrateur. Nous aurions tout aussi bien pu faire :
1
2

for nombre in mon_generateur () : # Attention on ex cute la


fonction
print ( nombre )

Cela rend quand mme le code bien plus simple comprendre.


Notez quon doit excuter la fonction mon_generateur pour obtenir un gnrateur. Si
vous essayez de parcourir notre fonction (for nombre in mon_generateur), cela ne
marchera pas.
Bien entendu, la plupart du temps, on ne se contentera pas dappeler yield comme cela.
Le gnrateur de notre exemple na pas beaucoup dintrt, il faut bien le reconnatre.
Essayons de faire une chose un peu plus utile : un gnrateur prenant en paramtres
deux entiers, une borne infrieure et une borne suprieure, et renvoyant chaque entier compris entre ces bornes. Si on crit par exemple intervalle(5, 10), on pourra
parcourir les entiers de 6 9.
Le rsultat attendu est donc :
1
2
3
4
5
6
7
8

>>> for nombre in intervalle (5 , 10) :


...
print ( nombre )
...
6
7
8
9
>>>

244

LES GNRATEURS
Vous pouvez essayer de faire lexercice, cest un bon entranement et pas trs compliqu
de surcrot.
Au cas o, voici la correction :
1
2

def intervalle ( borne_inf , borne_sup ) :


""" G n rateur parcourant la s rie des entiers entre
borne_inf et borne_sup .

3
4

Note : borne_inf doit tre inf rieure borne_sup """

5
6
7
8
9

borne_inf += 1
while borne_inf < borne_sup :
yield borne_inf
borne_inf += 1

L encore, vous pouvez amliorer cette fonction. Pourquoi ne pas faire en sorte que, si
la borne infrieure est suprieure la borne suprieure, le parcours se fasse dans lautre
sens ?
Limportant est que vous compreniez bien lintrt et le mcanisme derrire. Je vous
encourage, l encore, tester, dissquer cette fonctionnalit, essayer de reprendre
les exemples ditrateurs et les convertir en gnrateurs.
Si, dans une classe quelconque, la mthode spciale __iter__ contient un appel
yield, alors ce sera ce gnrateur qui sera appel quand on voudra parcourir la boucle.
Mme quand Python passe par des gnrateurs, comme vous lavez vu, il utilise (implicitement) des itrateurs. Cest juste plus confortable pour le codeur, on na pas besoin
de crer une classe par itrateur ni de coder une mthode __next__, ni mme de lever
lexception StopIteration : Python fait tout cela pour nous. Pratique non ?

Les gnrateurs comme co-routines


Jusquici, que ce soit avec les itrateurs ou avec les gnrateurs, nous crons un moyen
de parcourir notre objet au dbut de la boucle for, en sachant que nous ne pourrons
pas modifier le comportement du parcours par la suite. Mais les gnrateurs possdent
un certain nombre de mthodes permettant, justement, dinteragir avec eux pendant
le parcours.
Malheureusement, notre niveau, les ides dapplications utiles me manquent et je vais
me contenter de vous prsenter la syntaxe et un petit exemple. Peut-tre trouverezvous par la suite une application utile des co-routines quand vous vous lancerez dans
des programmes consquents, ou que vous aurez t plus loin dans lapprentissage du
Python.
Les co-routines sont un moyen daltrer le parcours. . . pendant le parcours. Par
exemple, dans notre gnrateur intervalle, on pourrait vouloir passer directement
de 5 10.
Le systme des co-routines en Python est contenu dans le mot-cl yield que nous avons
vu plus haut et lutilisation de certaines mthodes de notre gnrateur.
245

CHAPITRE 22. DERRIRE LA BOUCLE FOR


Interrompre la boucle
La premire mthode que nous allons voir est close. Elle permet dinterrompre prmaturment la boucle, comme le mot-cl break en somme.
1
2
3
4

generateur = intervalle (5 , 20 )
for nombre in generateur :
if nombre > 17 :
generateur . close () # Interruption de la boucle

Comme vous le voyez, pour appeler les mthodes du gnrateur, on doit le stocker
dans une variable avant la boucle. Si vous aviez crit directement for nombre in
intervalle(5, 20), vous nauriez pas pu appeler la mthode close du gnrateur.
Envoyer des donnes notre gnrateur
Pour cet exemple, nous allons tendre notre gnrateur pour quil accepte de recevoir
des donnes pendant son excution.
Le point dchange de donnes se fait au mot-cl yield. yield valeur renvoie
valeur qui deviendra donc la valeur courante du parcours. La fonction se met ensuite
en pause. On peut, cet instant, envoyer une valeur notre gnrateur. Cela permet
daltrer le fonctionnement de notre gnrateur pendant le parcours.
Reprenons notre exemple en intgrant cette fonctionnalit :
1
2
3
4
5

def intervalle ( borne_inf , borne_sup ) :


""" G n rateur parcourant la s rie des entiers entre
borne_inf et borne_sup .
Notre g n rateur doit pouvoir " sauter " une certaine plage
de nombres
en fonction d ' une valeur qu ' on lui donne pendant le
parcours . La
valeur qu ' on lui passe est la nouvelle valeur de borne_inf .

6
7
8
9
10
11
12
13

Note : borne_inf doit tre inf rieure borne_sup """


borne_inf += 1
while borne_inf < borne_sup :
valeur_recue = ( yield borne_inf )
if valeur_recue is not None : # Notre g n rateur a re u
quelque chose
borne_inf = valeur_recue
borne_inf += 1

Nous configurons notre gnrateur pour quil accepte une valeur ventuelle au cours du
parcours. Sil reoit une valeur, il va lattribuer au point du parcours.
Autrement dit, au cours de la boucle, vous pouvez demander au gnrateur de sauter
tout de suite 20 si le nombre est 15.
Tout se passe partir de la ligne du yield. Au lieu de simplement renvoyer une valeur
notre boucle, on capture une ventuelle valeur dans valeur_recue. La syntaxe est
246

LES GNRATEURS
simple : variable = (yield valeur_a_renvoyer) 1 .
Si aucune valeur na t passe notre gnrateur, notre valeur_recue vaudra None.
On vrifie donc si elle ne vaut pas None et, dans ce cas, on affecte la nouvelle valeur
borne_inf.
Voici le code permettant dinteragir avec notre gnrateur. On utilise la mthode send
pour envoyer une valeur notre gnrateur :
1
2
3
4
5

generateur = intervalle ( 10 , 25 )
for nombre in generateur :
if nombre == 15 : # On saute 20
generateur . send ( 20 )
print ( nombre , end = " " )

Il existe dautres mthodes permettant dinteragir avec notre gnrateur. Vous pouvez
les retrouver, ainsi que des explications supplmentaires, sur la documentation officielle
traitant du mot-cl yield avec le code web suivant :


Le mot-cl yield
B
Code web : 302240

En rsum
Quand on utilise la boucle for element in sequence:, un itrateur de cette squence permet de la parcourir.
On peut rcuprer litrateur dune squence grce la fonction iter.
Une squence renvoie litrateur permettant de la parcourir grce la mthode spciale __iter__.
Un itrateur possde une mthode spciale, __next__, qui renvoie le prochain lment parcourir ou lve lexception StopIteration qui arrte la boucle.
Les gnrateurs permettent de crer plus simplement des itrateurs.
Ce sont des fonctions utilisant le mot-cl yield suivi de la valeur transmettre la
boucle.

1. Noubliez pas les parenthses autour de yield valeur.

247

CHAPITRE 22. DERRIRE LA BOUCLE FOR

248

Chapitre

23

TP : un dictionnaire ordonn
Difficult :
oici enfin le moment de la pratique. Vous avez appris pas mal de choses dans cette
partie, beaucoup de concepts, souvent thoriques. Il est temps de les mettre en application, dans un contexte un peu diffrent des TP prcdents : on ne va pas crer
un jeu mais plutt un objet conteneur tenant la fois du dictionnaire et de la liste.

249

CHAPITRE 23. TP : UN DICTIONNAIRE ORDONN

Notre mission
Notre nonc va tre un peu diffrent de ceux dont vous avez lhabitude. Nous nallons pas crer ici un jeu mais simplement une classe, destine produire des objets
conteneurs, des dictionnaires ordonns.
Peut-tre ne vous en souvenez-vous pas mais je vous ai dit dans le chapitre consacr aux
dictionnaires que ctait un type non-ordonn. Ainsi, lordre dans lequel vous entrez les
donnes na pas dimportance. On ne peut ni les trier, ni les inverser, tout cela naurait
aucun sens pour ce type particulier.
Mais nous allons profiter de loccasion pour crer une forme de dictionnaire ordonn.
Lide, assez simplement, est de stocker nos donnes dans deux listes :
la premire contenant nos cls ;
la seconde contenant les valeurs correspondantes.
Lordre dajout sera ainsi important, on pourra trier et inverser ce type de dictionnaire.

Spcifications
Voici la liste des mcanismes que notre classe devra mettre en uvre. Un peu plus bas,
vous trouverez un exemple de manipulation de lobjet qui reprend ces spcifications :
1. On doit pouvoir crer le dictionnaire de plusieurs faons :
Vide : on appelle le constructeur sans lui passer aucun paramtre et le dictionnaire cr est donc vide.
Copi depuis un dictionnaire : on passe en paramtre du constructeur un dictionnaire que lon copie par la suite dans notre objet. On peut ainsi crire
constructeur(dictionnaire) et les cls et valeurs contenues dans le dictionnaire sont copies dans lobjet construit.
Pr-rempli grce des cls et valeurs passes en paramtre : comme les dictionnaires usuels, on doit ici avoir la possibilit de pr-remplir notre objet avec
des couples cls-valeurs passs en paramtre (constructeur(cle1 = valeur1,
cle2 = valeur2, ...)).
2. Les cls et valeurs doivent tre couples. Autrement dit, si on cherche supprimer une cl, la valeur correspondante doit galement tre supprime. Les cls et
valeurs se trouvant dans des listes de mme taille, il suffira de prendre lindice
dans une liste pour savoir quel objet lui correspond dans lautre. Par exemple, la
cl dindice 0 est couple avec la valeur dindice 0.
3. On doit pouvoir interagir avec notre objet conteneur grce aux crochets, pour
rcuprer une valeur (objet[cle]), pour la modifier (objet[cle] = valeur) ou
pour la supprimer (del objet[cle]).
4. Quand on cherche modifier une valeur, si la cl existe on crase lancienne
valeur, si elle nexiste pas on ajoute le couple cl-valeur la fin du dictionnaire.
5. On doit pouvoir savoir grce au mot-cl in si une cl se trouve dans notre dictionnaire (cle in dictionnaire).
250

NOTRE MISSION
6. On doit pouvoir demander la taille du dictionnaire grce la fonction len.
7. On doit pouvoir afficher notre dictionnaire directement dans linterprteur ou
grce la fonction print. Laffichage doit tre similaire celui des dictionnaires
usuels ({cle1: valeur1, cle2: valeur2, ...}).
8. Lobjet doit dfinir les mthodes sort pour le trier et reverse pour linverser.
Le tri de lobjet doit se faire en fonction des cls.
9. Lobjet doit pouvoir tre parcouru. Quand on crit for cle in dictionnaire,
on doit parcourir la liste des cls contenues dans le dictionnaire.
10. linstar des dictionnaires, trois mthodes keys() (renvoyant la liste des cls),
values() (renvoyant la liste des valeurs) et items() (renvoyant les couples (cl,
valeur)) doivent tre mises en uvre. Le type de retour de ces mthodes est laiss
votre initiative : il peut sagir ditrateurs ou de gnrateurs (tant quon peut
les parcourir).
11. On doit pouvoir ajouter deux dictionnaires ordonns (dico1 + dico2) ; les cls
et valeurs du second dictionnaire sont ajoutes au premier.
Cela vous en fait, du boulot !
Et vous pourrez encore trouver le moyen damliorer votre classe par la suite, si vous
le dsirez.

Exemple de manipulation
Ci-dessous se trouve un exemple de manipulation de notre dictionnaire ordonn. Quand
vous aurez cod le vtre, vous pourrez voir sil ragit de la mme faon que le mien.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

>>> fruits = DictionnaireOrdonne ()


>>> fruits
{}
>>> fruits [" pomme "] = 52
>>> fruits [" poire "] = 34
>>> fruits [" prune "] = 128
>>> fruits [" melon "] = 15
>>> fruits
{ pomme : 52 , poire : 34 , prune : 128 , melon : 15}
>>> fruits . sort ()
>>> print ( fruits )
{ melon : 15 , poire : 34 , pomme : 52 , prune : 128}
>>> legumes = DictionnaireOrdonne ( carotte = 26 , haricot = 48)
>>> print ( legumes )
{ carotte : 26 , haricot : 48}
>>> len ( legumes )
2
>>> legumes . reverse ()
>>> fruits = fruits + legumes
>>> fruits
{ melon : 15 , poire : 34 , pomme : 52 , prune : 128 , haricot
: 48 , carotte :

251

CHAPITRE 23. TP : UN DICTIONNAIRE ORDONN


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

26}
>>> del fruits [ haricot ]
>>> haricot in fruits
False
>>> legumes [ haricot ]
48
>>> for cle in legumes :
...
print ( cle )
...
haricot
carotte
>>> legumes . keys ()
[ haricot , carotte ]
>>> legumes . values ()
[48 , 26]
>>> for nom , qtt in legumes . items () :
...
print ("{0} ({1}) ". format ( nom , qtt ) )
...
haricot (48)
carotte (26)
>>>

Tous au dpart !
Je vous ai donn le ncessaire, cest maintenant vous de jouer. Concernant limplmentation, les fonctionnalits, il reste des zones obscures, cest volontaire. Tout ce qui
nest pas clairement dit est votre initiative. Tant que cela fonctionne et que lexemple
de manipulation ci-dessus affiche la mme chose chez vous, cest parfait. Si vous voulez
mettre en uvre dautres fonctionnalits, mthodes ou attributs, ne vous gnez pas. . .
mais noubliez pas dy aller progressivement. Cest parti !

Correction propose
Voici la correction que je vous propose. Je suis sr que vous tes, de votre ct, arrivs
quelque chose, mme si tout ne fonctionne pas encore parfaitement. Certaines fonctionnalits, comme le tri, laffichage, etc. sont encore un peu complexes apprhender.
Cependant, faites attention ne pas sauter trop rapidement la correction et essayez
au moins dobtenir par vous-mmes un dictionnaire ordonn avec des fonctionnalits
oprationnelles dajout, de consultation et de suppression dlments.


Copier ce code
B
Code web : 167286


ATTENTION LES YEUX. . .

252

CORRECTION PROPOSE
1
2
3
4

class D ic t io n naireOrdonne :
""" Notre dictionnaire ordonn . L ' ordre des donn es est
maintenu
et il peut donc , contrairement aux dictionnaires usuels ,
tre tri
ou voir l ' ordre de ses donn es invers es """

5
6
7
8
9
10
11

def __init__ ( self , base = { } , ** donnees ) :


""" Constructeur de notre objet . Il peut ne prendre
aucun param tre
( dans ce cas , le dictionnaire sera vide ) ou construire
un
dictionnaire remplis gr ce :
au dictionnaire ' base ' pass en premier param tre ;
aux valeurs que l ' on retrouve dans ' donnees '. """

12
13
14

self . _cles = [] # Liste contenant nos cl s


self . _valeurs = [] # Liste contenant les valeurs
correspondant nos cl s

15
16
17
18
19

# On v rifie que ' base ' est un dictionnaire exploitable


if type ( base ) not in ( dict , DictionnaireOrdonne ) :
raise TypeError ( \
" le type attendu est un dictionnaire ( usuel ou
ordonne ) " )

20
21
22
23

# On r cup re les donn es de ' base '


for cle in base :
self [ cle ] = base [ cle ]

24
25
26
27

# On r cup re les donn es de ' donnees '


for cle in donnees :
self [ cle ] = donnees [ cle ]

28
29
30
31
32

def __repr__ ( self ) :


""" Repr sentation de notre objet . C ' est cette cha ne
qui sera affich e
quand on saisit directement le dictionnaire dans l '
interpr teur , ou en
utilisant la fonction ' repr ' """

33
34
35
36
37
38
39
40
41

chaine = " { "


premier_passage = True
for cle , valeur in self . items () :
if not premier_passage :
chaine += " , " # On ajoute la virgule comme s
parateur
else :
premier_passage = False
chaine += repr ( cle ) + " : " + repr ( valeur )

253

CHAPITRE 23. TP : UN DICTIONNAIRE ORDONN


42
43

chaine += " } "


return chaine

44
45
46
47
48

def __str__ ( self ) :


""" Fonction appel e quand on souhaite afficher le
dictionnaire gr ce
la fonction ' print ' ou le convertir en cha ne gr ce
au constructeur
' str '. On redirige sur __repr__ """

49
50

return repr ( self )

51
52
53
54

def __len__ ( self ) :


""" Renvoie la taille du dictionnaire """
return len ( self . _cles )

55
56
57
58

def __contains__ ( self , cle ) :


""" Renvoie True si la cl est dans la liste des cl s ,
False sinon """
return cle in self . _cles

59
60
61
62

def __getitem__ ( self , cle ) :


""" Renvoie la valeur correspondant la cl si elle
existe , l ve
une exception KeyError sinon """

63
64
65
66
67
68
69
70

if cle not in self . _cles :


raise KeyError ( \
" La cl { 0 } ne se trouve pas dans le
dictionnaire " . format ( \
cle ) )
else :
indice = self . _cles . index ( cle )
return self . _valeurs [ indice ]

71
72
73
74
75

def __setitem__ ( self , cle , valeur ) :


""" M thode sp ciale appel e quand on cherche modifier
une cl
pr sente dans le dictionnaire . Si la cl n ' est pas pr
sente , on l ' ajoute
la fin du dictionnaire """

76
77
78
79
80
81
82

if cle in self . _cles :


indice = self . _cles . index ( cle )
self . _valeurs [ indice ] = valeur
else :
self . _cles . append ( cle )
self . _valeurs . append ( valeur )

83
84

254

def __delitem__ ( self , cle ) :

CORRECTION PROPOSE
85
86
87
88
89
90
91
92
93

""" M thode appel e quand on souhaite supprimer une cl


"""
if cle not in self . _cles :
raise KeyError ( \
" La cl { 0 } ne se trouve pas dans le
dictionnaire " . format ( \
cle ) )
else :
indice = self . _cles . index ( cle )
del self . _cles [ indice ]
del self . _valeurs [ indice ]

94
95
96
97

def __iter__ ( self ) :


""" M thode de parcours de l ' objet . On renvoie l ' it
rateur des cl s """
return iter ( self . _cles )

98
99
100
101

def __add__ ( self , autre_objet ) :


""" On renvoie un nouveau dictionnaire contenant les
deux
dictionnaires mis bout bout ( d ' abord self puis
autre_objet ) """

102
103
104
105
106
107
108

if type ( autre_objet ) is not type ( self ) :


raise TypeError ( \
" Impossible de concat ner { 0 } et { 1 } " . format ( \
type ( self ) , type ( autre_objet ) ) )
else :
nouveau = DictionnaireOrdonne ()

109
110
111
112

# On commence par copier self dans le dictionnaire


for cle , valeur in self . items () :
nouveau [ cle ] = valeur

113
114
115
116
117

# On copie ensuite autre_objet


for cle , valeur in autre_objet . items () :
nouveau [ cle ] = valeur
return nouveau

118
119
120
121
122
123

def items ( self ) :


""" Renvoie un g n rateur contenant les couples ( cle ,
valeur ) """
for i , cle in enumerate ( self . _cles ) :
valeur = self . _valeurs [ i ]
yield ( cle , valeur )

124
125
126
127

def keys ( self ) :


""" Cette m thode renvoie la liste des cl s """
return list ( self . _cles )

128

255

CHAPITRE 23. TP : UN DICTIONNAIRE ORDONN


129
130
131

def values ( self ) :


""" Cette m thode renvoie la liste des valeurs """
return list ( self . _valeurs )

132
133
134
135
136
137
138
139
140
141
142
143
144
145

def reverse ( self ) :


""" Inversion du dictionnaire """
# On cr e deux listes vides qui contiendront le nouvel
ordre des cl s
# et valeurs
cles = []
valeurs = []
for cle , valeur in self . items () :
# On ajoute les cl s et valeurs au d but de la
liste
cles . insert (0 , cle )
valeurs . insert (0 , valeur )
# On met ensuite jour nos listes
self . _cles = cles
self . _valeurs = valeurs

146
147
148
149
150
151
152
153
154
155
156
157
158
159

def sort ( self ) :


""" M thode permettant de trier le dictionnaire en
fonction de ses cl s """
# On trie les cl s
cles_triees = sorted ( self . _cles )
# On cr e une liste de valeurs , encore vide
valeurs = []
# On parcourt ensuite la liste des cl s tri es
for cle in cles_triees :
valeur = self [ cle ]
valeurs . append ( valeur )
# Enfin , on met jour notre liste de cl s et de
valeurs
self . _cles = cles_triees
self . _valeurs = valeurs

Le mot de la fin
Le but de lexercice tait de prsenter un nonc simple et laissant de la place aux
choix de programmation. Ce que je vous propose nest pas lunique faon de faire, ni la
meilleure. Lexercice vous a surtout permis de travailler sur des notions concrtes que
nous tudions depuis le dbut de cette partie et de construire un objet conteneur qui
nest pas dpourvu dutilit.
Nhsitez pas amliorer notre objet, il nen sera que plus joli et utile avec des fonctionnalits supplmentaires !
Ne vous alarmez pas si vous navez pas russi coder tous les aspects du dictionnaire.
Lessentiel est davoir essay et compris la correction.
256

Chapitre

24

Les dcorateurs
Difficult :
ous allons ici nous intresser un concept fascinant de Python, un concept de
programmation assez avanc. Vous ntes pas obligs de lire ce chapitre pour la suite
de ce livre, ni mme connatre cette fonctionnalit pour coder en Python. Il sagit
dun plus que jai voulu dtailler mais qui nest certainement pas indispensable.

Les dcorateurs sont un moyen simple de modifier le comportement par dfaut de


fonctions. Cest un exemple assez flagrant de ce quon appelle la mtaprogrammation,
que je vais dcrire assez brivement comme lcriture de programmes manipulant. . . dautres
programmes. Cela donne faim, non ?

257

CHAPITRE 24. LES DCORATEURS

Quest-ce que cest ?


Les dcorateurs sont des fonctions de Python dont le rle est de modifier le comportement par dfaut dautres fonctions ou classes. Pour schmatiser, une fonction modifie
par un dcorateur ne sexcutera pas elle-mme mais appellera le dcorateur. Cest au
dcorateur de dcider sil veut excuter la fonction et dans quelles conditions.
Mais quel est lintrt ? Si on veut juste quune fonction fasse quelque chose
de diffrent, il suffit de la modifier, non ? Pourquoi sencombrer la tte avec
une nouvelle fonctionnalit plus complexe ?
Il peut y avoir de nombreux cas dans lesquels les dcorateurs sont un choix intressant.
Pour comprendre lide, je vais prendre un unique exemple.
On souhaite tester les performances de certaines de nos fonctions, en loccurence, calculer combien de temps elles mettent pour sexcuter.
Une possibilit, effectivement, consiste modifier chacune des fonctions devant intgrer
ce test. Mais ce nest pas trs lgant, ni trs pratique, ni trs sr. . . bref ce nest pas
la meilleure solution.
Une autre possibilit consiste utiliser un dcorateur. Ce dcorateur se chargera dexcuter notre fonction en calculant le temps quelle met et pourra, par exemple, afficher
une alerte si cette dure est trop leve.
Pour indiquer quune fonction doit intgrer ce test, il suffira dajouter une simple ligne
avant sa dfinition. Cest bien plus simple, clair et adapt la situation.
Et ce nest quun exemple dapplication.
Les dcorateurs sont des fonctions standard de Python mais leur construction est parfois
complexe. Quand il sagit de dcorateurs prenant des arguments en paramtres ou
devant tenir compte des paramtres de la fonction, le code est plus complexe, moins
intuitif.
Je vais faire mon possible pour que vous compreniez bien le principe. Nhsitez pas
y revenir tte repose, une, deux, trois fois pour que cela soit bien clair.

En thorie
Une fois nest pas coutume, je vais vous montrer les diffrentes constructions possibles
en thorie avec quelques exemples, mais je vais aussi consacrer une section entire
des exemples dutilisations pour expliciter cette partie thorique indispensable.

Format le plus simple


Comme je lai dit, les dcorateurs sont des fonctions classiques de Python, dans leur
dfinition. Ils ont une petite subtilit en ce quils prennent en paramtre une fonction
258

EN THORIE
et renvoient une fonction.
On dclare quune fonction doit tre modifie par un (ou plusieurs) dcorateurs grce
une (ou plusieurs) lignes au-dessus de la dfinition de fonction, comme ceci :
1
2

@n om _d u_d ec or ateur
def ma_fonction (...)

Le dcorateur sexcute au moment de la dfinition de fonction et non lors de lappel.


Ceci est important. Il prend en paramtre, comme je lai dit, une fonction (celle quil
modifie) et renvoie une fonction (qui peut tre la mme).
Voyez plutt :
1
2
3
4
5
6
7
8
9
10
11
12

>>> def mon_decorateur ( fonction ) :


...
""" Premier exemple de d corateur """
...
print (" Notre d corateur est appel avec en param tre la
fonction {0}". format ( fonction ) )
...
return fonction
...
>>> @mon_decorateur
... def salut () :
...
""" Fonction modifi e par notre d corateur """
...
print (" Salut !")
...
Notre d corateur est appel avec en param tre la fonction <
function salut at 0 x00BA5198 >
>>>

Euh. . . quest-ce quon a fait l ?

Dabord, on cre le dcorateur. Il prend en paramtre, comme je vous lai dit, la


fonction quil modifie. Dans notre exemple, il se contente dafficher cette fonction
puis de la renvoyer.
On cre ensuite la fonction salut. Comme vous le voyez, on indique avant la dfinition la ligne @mon_decorateur, qui prcise Python que cette fonction doit tre
modifie par notre dcorateur. Notre fonction est trs utile : elle affiche Salut ! et
cest tout.
la fin de la dfinition de notre fonction, on peut voir que le dcorateur est appel.
Si vous regardez plus attentivement la ligne affiche, vous vous rendez compte quil
est appel avec, en paramtre, la fonction salut que nous venons de dfinir.
Intressons-nous un peu plus la structure de notre dcorateur. Il prend en paramtre
la fonction modifier (celle que lon dfinit sous la ligne du @), je pense que vous avez
pu le constater. Mais il renvoie galement cette fonction et cela, cest un peu moins
vident !
En fait, la fonction renvoye remplace la fonction dfinie. Ici, on renvoie la fonction
259

CHAPITRE 24. LES DCORATEURS


dfinie, cest donc la mme. Mais on peut demander Python dexcuter une autre
fonction la place, pour modifier son comportement. Nous allons voir cela un peu plus
loin.
Pour lheure, souvenez-vous que les deux codes ci-dessous sont identiques :
1
2
3
4
1
2
3

# Exemple avec d corateur


@decorateur
def fonction (...) :
...
# Exemple quivalent , sans d corateur
def fonction (...) :
...

4
5

fonction = decorateur ( fonction )

Relisez bien ces deux codes, ils font la mme chose. Le second est l pour que vous
compreniez ce que fait Python quand il manipule des fonctions modifies par un (ou
plusieurs) dcorateur(s).
Quand vous excutez salut, vous ne voyez aucun changement. Et cest normal puisque
nous renvoyons la mme fonction. Le seul moment o notre dcorateur est appel, cest
lors de la dfinition de notre fonction. Notre fonction salut na pas t modifie par
notre dcorateur, on sest content de la renvoyer telle quelle.

Modifier le comportement de notre fonction


Vous laurez devin, un dcorateur comme nous lavons cr plus haut nest pas bien
utile. Les dcorateurs servent surtout modifier le comportement dune fonction. Je
vous montre cependant pas pas comment cela fonctionne, sinon vous risquez de vite
vous perdre.
Comment faire pour modifier le comportement de notre fonction ?

En fait, vous avez un lment de rponse un peu plus haut. Jai dit que notre dcorateur
prenait en paramtre la fonction dfinie et renvoyait une fonction (peut-tre la mme,
peut-tre une autre). Cest cette fonction renvoye qui sera directement affecte notre
fonction dfinie. Si vous aviez renvoy une autre fonction que salut, dans notre exemple
ci-dessus, la fonction salut aurait redirig vers cette fonction renvoye.

Mais alors. . . il faut dfinir encore une fonction ?

Eh oui ! Je vous avais prvenus (et ce nest que le dbut), notre construction se complexifie au fur et mesure : on va devoir crer une nouvelle fonction qui sera charge
260

EN THORIE
de modifier le comportement de la fonction dfinie. Et, parce que notre dcorateur sera
le seul utiliser cette fonction, on va la dfinir directement dans le corps de notre
dcorateur.
Je suis perdu. Comment cela marche-t-il, concrtement ?

Je vais vous mettre le code, cela vaudra mieux que des tonnes dexplications. Je le
commente un peu plus bas, ne vous inquitez pas :
1
2
3

def mon_decorateur ( fonction ) :


""" Notre d corateur : il va afficher un message avant l '
appel de la
fonction d finie """

4
5
6
7
8
9

def fonc tion_modifiee () :


""" Fonction que l ' on va renvoyer . Il s ' agit en fait d '
une version
un peu modifi e de notre fonction originellement d
finie . On se
contente d ' afficher un avertissement avant d ' ex cuter
notre fonction
originellement d finie """

10
11
12
13

print ( " Attention ! On appelle { 0 } " . format ( fonction ) )


return fonction ()
return fonction_modifiee

14
15
16
17

@mon_decorateur
def salut () :
print ( " Salut ! " )

Voyons leffet, avant les explications. Aucun message ne saffiche en excutant ce code.
Par contre, si vous excutez votre fonction salut :
1
2
3
4

>>> salut ()
Attention ! On appelle < function salut at 0 x00BA54F8 >
Salut !
>>>

Et si vous affichez la fonction salut dans linterprteur, vous obtenez quelque chose de
surprenant :
1
2
3

>>> salut
< function fonction_modifiee at 0 x00BA54B0 >
>>>

Pour comprendre, revenons sur le code de notre dcorateur :


261

CHAPITRE 24. LES DCORATEURS


Comme toujours, il prend en paramtre une fonction. Cette fonction, quand on place
lappel au dcorateur au-dessus de def salut, cest salut (la fonction dfinie
lorigine).
Dans le corps mme de notre dcorateur, vous pouvez voir quon a dfini une nouvelle fonction, fonction_modifiee. Elle ne prend aucun paramtre, elle nen a pas
besoin. Dans son corps, on affiche une ligne avertissant quon va excuter la fonction
fonction (l encore, il sagit de salut). la ligne suivante, on lexcute effectivement et on renvoie le rsultat de son excution (dans le cas de salut, il ny en a pas
mais dautres fonctions pourraient renvoyer des informations).
De retour dans notre dcorateur, on indique quil faut renvoyer fonction_modifiee.
Lors de la dfinition de notre fonction salut, on appelle notre dcorateur. Python lui
passe en paramtre la fonction salut. Cette fois, notre dcorateur ne renvoie pas salut
mais fonction_modifiee. Et notre fonction salut, que nous venons de dfinir, sera
donc remplace par notre fonction fonction_modifiee, dfinie dans notre dcorateur.
Vous le voyez bien, dailleurs : quand on cherche afficher salut dans linterprteur,
on obtient fonction_modifiee.
Souvenez-vous bien que le code :
1
2
3

@mon_decorateur
def salut () :
...

revient au mme, pour Python, que le code :


1
2

def salut () :
...

salut = mon_decorateur ( salut )

Ce nest peut-tre pas plus clair. Prenez le temps de lire et de bien comprendre
lexemple. Ce nest pas simple, la logique est bel et bien l mais il faut passer un
certain temps tester avant de bien intgrer cette notion.
Pour rsumer, notre dcorateur renvoie une fonction de substitution. Quand on appelle
salut, on appelle en fait notre fonction modifie qui appelle galement salut aprs
avoir affich un petit message davertissement.
Autre exemple : un dcorateur charg tout simplement dempcher lexcution de la
fonction. Au lieu dexcuter la fonction dorigine, on lve une exception pour avertir
lutilisateur quil utilise une fonctionnalit obsolte.
1
2
3

def obsolete ( fonction_origine ) :


""" D corateur levant une exception pour noter que la
fonction_origine
est obsol te """

4
5
6
7

262

def fonction_modifiee () :
raise RuntimeError ( " la fonction { 0 } est obsol te ! " .
format ( fonction_origine ) )
return fonction_modifiee

EN THORIE
L encore, faites quelques essais : tout deviendra limpide aprs quelques manipulations.

Un dcorateur avec des paramtres


Toujours plus dur ! On voudrait maintenant passer des paramtres notre dcorateur.
Nous allons essayer de coder un dcorateur charg dexcuter une fonction en contrlant
le temps quelle met sexcuter. Si elle met un temps suprieur la dure passe en
paramtre du dcorateur, on affiche une alerte.
La ligne appelant notre dcorateur, au-dessus de la dfinition de notre fonction, sera
donc sous la forme :
1

@controler_temps ( 2 . 5 ) # 2 , 5 secondes maximum pour la fonction


ci - dessous

Jusquici, nos dcorateurs ne comportaient aucune parenthse aprs leur appel. Ces
deux parenthses sont trs importantes : notre fonction de dcorateur prendra en paramtres non pas une fonction, mais les paramtres du dcorateur (ici, le temps maximum
autoris pour la fonction). Elle ne renverra pas une fonction de substitution, mais un
dcorateur.
Encore et toujours perdu. Pourquoi est-ce si compliqu de passer des paramtres notre dcorateur ?
En fait. . . ce nest pas si compliqu que cela mais cest dur saisir au dbut. Pour mieux
comprendre, essayez encore une fois de vous souvenir que ces deux codes reviennent au
mme :
1
2
3
1
2

@decorateur
def fonction (...) :
...
def fonction (...) :
...

3
4

fonction = decorateur ( fonction )

Cest la dernire ligne du second exemple que vous devez retenir et essayer de comprendre : fonction = decorateur(fonction).
On remplace la fonction que nous avons dfinie au-dessus par la fonction que renvoie
notre dcorateur.
Cest le mcanisme qui se cache derrire notre @decorateur.
Maintenant, si notre dcorateur attend des paramtres, on se retrouve avec une ligne
comme celle-ci :
1
2
3

@decorateur ( parametre )
def fonction (...) :
...

263

CHAPITRE 24. LES DCORATEURS


Et si vous avez compris lexemple ci-dessus, ce code revient au mme que :
1
2

def fonction (...) :


...

fonction = decorateur ( parametre ) ( fonction )

Je vous avais prvenus, ce nest pas trs intuitif ! Mais relisez bien ces exemples, le
dclic devrait se faire tt ou tard.
Comme vous le voyez, on doit dfinir comme dcorateur une fonction qui prend en
arguments les paramtres du dcorateur (ici, le temps attendu) et qui renvoie un dcorateur. Autrement dit, on se retrouve encore une fois avec un niveau supplmentaire
dans notre fonction.
Je vous donne le code sans trop insister. Si vous arrivez comprendre la logique qui se
trouve derrire, cest tant mieux, sinon nhsitez pas y revenir plus tard :
1
2
3
4
5

""" Pour g rer le temps , on importe le module time


On va utiliser surtout la fonction time () de ce module qui
renvoie le nombre
de secondes coul es depuis le premier janvier 1970 (
habituellement ) .
On va s ' en servir pour calculer le temps mis par notre fonction
pour
s ' ex cuter """

import time

7
8
9
10
11

def controler_temps ( nb_secs ) :


""" Contr le le temps mis par une fonction pour s ' ex cuter .
Si le temps d ' ex cution est sup rieur nb_secs , on affiche
une alerte """

12
13
14
15

def decorateur ( fonction_a_executer ) :


""" Notre d corateur . C ' est lui qui est appel
directement LORS
DE LA DEFINITION de notre fonction ( fonction_a_executer
) """

16
17
18
19

def fonction_modifiee () :
""" Fonction renvoy e par notre d corateur . Elle se
charge
de calculer le temps mis par la fonction s ' ex
cuter """

20
21
22
23
24

264

tps_avant = time . time () # Avant d ' ex cuter la


fonction
valeur_renvoyee = fonction_a_executer () # On ex
cute la fonction
tps_apres = time . time ()
tps_execution = tps_apres - tps_avant

EN THORIE
if tps_execution >= nb_secs :
print ( " La fonction { 0 } a mis { 1 } pour s ' ex
cuter " . format ( \
fonction_a_executer , tps_execution ) )
return valeur_renvoyee
return fonction_modifiee
return decorateur

25
26
27
28
29
30

Ouf ! Trois niveaux dans notre fonction ! Dabord controler_temps, qui dfinit dans
son corps notre dcorateur decorateur, qui dfinit lui-mme dans son corps notre
fonction modifie fonction_modifiee.
Jespre que vous ntes pas trop embrouills. Je le rpte, il sagit dune fonctionnalit
trs puissante mais qui nest pas trs intuitive quand on ny est pas habitu. Jetez un
coup dil du ct des exemples au-dessus si vous tes un peu perdus.
Nous pouvons maintenant utiliser notre dcorateur. Jai fait une petite fonction pour
tester quun message saffiche bien si notre fonction met du temps sexcuter. Voyez
plutt :
1
2
3
4
5
6
7
8
9
10

>>> @controler_temps (4)


... def attendre () :
...
input (" Appuyez sur Entr e ... ")
...
>>> attendre () # Je vais appuyer sur Entr e presque tout de
suite
Appuyez sur Entr e ...
>>> attendre () # Cette fois , j attends plus longtemps
Appuyez sur Entr e ...
La fonction < function attendre at 0 x00BA5810 > a mis
4.14100003242 pour s ex cuter
>>>

a marche ! Et mme si vous devez passer un peu de temps sur votre dcorateur, vu
ses diffrents niveaux, vous tes obligs de reconnatre quil sutilise assez simplement.
Il est quand mme plus intuitif dcrire :
1
2
3

@controler_temps ( 4 )
def attendre (...)
...

que :
1
2

def attendre (...) :


...

3
4

attendre = controler_temps ( 4 ) ( attendre )

265

CHAPITRE 24. LES DCORATEURS

Tenir compte des paramtres de notre fonction


Jusquici, nous navons travaill quavec des fonctions ne prenant aucun paramtre.
Cest pourquoi notre fonction fonction_modifiee nen prenait pas non plus.
Oui mais. . . tenir compte des paramtres, cela peut tre utile. Sans quoi on ne pourrait
construire que des dcorateurs sappliquant des fonctions sans paramtre.
Il faut, pour tenir compte des paramtres de la fonction, modifier ceux de notre fonction
fonction_modifiee. L encore, je vous invite regarder les exemples ci-dessus, explicitant ce que Python fait rellement lorsquon dfinit un dcorateur avant une fonction.
Vous pourrez vous rendre compte que fonction_modifiee remplace notre fonction et
que, par consquent, elle doit prendre des paramtres si notre fonction dfinie prend
galement des paramtres.
Cest dans ce cas en particulier que nous allons pouvoir rutiliser la notation spciale
pour nos fonctions attendant un nombre variable darguments. En effet, le dcorateur
que nous avons cr un peu plus haut devrait pouvoir sappliquer des fonctions ne
prenant aucun paramtre, ou en prenant un, ou plusieurs. . . au fond, notre dcorateur
ne doit ni savoir combien de paramtres sont fournis notre fonction, ni mme sen
soucier.
L encore, je vous donne le code adapt de notre fonction modifie. Souvenez-vous
quelle est dfinie dans notre decorateur, lui-mme dfini dans controler_temps (je
ne vous remets que le code de fonction_modifiee).

...

2
3
4

def fonction_modifiee (* parametres_non_nommes , **


parametres_nommes ) :
""" Fonction renvoy e par notre d corateur . Elle se
charge
de calculer le temps mis par la fonction s ' ex
cuter """

5
6
7
8
9
10
11
12
13

tps_avant = time . time () # avant d ' ex cuter la


fonction
ret = fonction_a_executer (* parametres_non_nommes ,
** parametres_nommes )
tps_apres = time . time ()
tps_execution = tps_apres - tps_avant
if tps_execution >= nb_secs :
print ( " La fonction { 0 } a mis { 1 } pour s ' ex
cuter " . format ( \
fonction_a_executer , tps_execution ) )
return ret

prsent, vous pouvez appliquer ce dcorateur des fonctions ne prenant aucun paramtre, ou en prenant un certain nombre, nomms ou non. Pratique, non ?
266

EXEMPLES DAPPLICATIONS

Des dcorateurs sappliquant aux dfinitions de classes


Vous pouvez galement appliquer des dcorateurs aux dfinitions de classes. Nous verrons un exemple dapplication dans la section suivante. Au lieu de recevoir en paramtre
la fonction, vous allez recevoir la classe.
1
2
3
4
5
6
7
8
9
10

>>> def decorateur ( classe ) :


...
print (" D finition de la classe {0}". format ( classe ) )
...
return classe
...
>>> @decorateur
... class Test :
...
pass
...
D finition de la classe < class __main__ . Test >
>>>

Voil. Vous verrez dans la section suivante quel peut tre lintrt de manipuler nos
dfinitions de classes travers des dcorateurs. Il existe dautres exemples que celui
que je vais vous montrer, bien entendu.

Chaner nos dcorateurs


Vous pouvez modifier une fonction ou une dfinition de classe par le biais de plusieurs
dcorateurs, sous la forme :
1
2
3

@decorateur1
@decorateur2
def fonction () :

Ce nest pas plus compliqu que ce que vous venez de faire. Je vous le montre pour quil
ne subsiste aucun doute dans votre esprit, vous pouvez tester loisir cette possibilit,
par vous-mmes.
Je vais prsent vous prsenter quelques applications possibles des dcorateurs, inspires en grande partie de la PEP 318, accessible avec le code web suivant :


PEP 318
B
Code web : 647141

Exemples dapplications
Nous allons voir deux exemples dapplications des dcorateurs dans cette section. Vous
en avez galement vu quelques-uns dans la section prcdente mais, maintenant que
vous matrisez la syntaxe, nous allons nous pencher sur des exemples plus parlants !
267

CHAPITRE 24. LES DCORATEURS

Les classes singleton


Certains reconnatront srement cette appellation. Pour les autres, sachez quune classe
dite singleton est une classe qui ne peut tre instancie quune fois.
Autrement dit, on ne peut crer quun seul objet de cette classe.
Cela peut-tre utile quand vous voulez tre absolument certains quune classe ne produira quun seul objet, quil est inutile (voire dangereux) davoir plusieurs objets de
cette classe. La premire fois que vous appelez le constructeur de ce type de classe,
vous obtenez le premier et lunique objet nouvellement instanci. Tout appel ultrieur
ce constructeur renvoie le mme objet (le premier cr).
Ceci est trs facile modliser grce des dcorateurs.
Code de lexemple
1
2
3
4
5
6
7
8

def singleton ( classe_definie ) :


instances = { } # Dictionnaire de nos instances singletons
def get_instance () :
if classe_definie not in instances :
# On cr e notre premier objet de classe_definie
instances [ classe_definie ] = classe_definie ()
return instances [ classe_definie ]
return get_instance

Explications
Dabord, pour utiliser notre dcorateur, cest trs simple : il suffit de mettre lappel
notre dcorateur avant la dfinition des classes que nous souhaitons utiliser en tant que
singleton :
1
2
3
4
5
6
7
8
9

>>> @singleton
... class Test :
...
pass
...
>>> a = Test ()
>>> b = Test ()
>>> a is b
True
>>>

Quand on cre notre premier objet (celui se trouvant dans a), notre constructeur est
bien appel. Quand on souhaite crer un second objet, cest celui contenu dans a qui
est renvoy. Ainsi, a et b pointent vers le mme objet.
Intressons-nous maintenant notre dcorateur. Il dfinit dans son corps un dictionnaire. Ce dictionnaire contient en guise de cl la classe singleton et en tant que valeur
lobjet cr correspondant. Il renvoie notre fonction interne get_instance qui va remplacer notre classe. Ainsi, quand on voudra crer un nouvel objet, ce sera get_instance
268

EXEMPLES DAPPLICATIONS
qui sera appele. Cette fonction vrifie si notre classe se trouve dans le dictionnaire.
Si ce nest pas le cas, on cre notre premier objet correspondant et on linsre dans le
dictionnaire. Dans tous les cas, on renvoie lobjet correspondant dans le dictionnaire
(soit il vient dtre cr, soit cest notre objet cr au premier appel du constructeur).
Grce ce systme, on peut avoir plusieurs classes dclares comme des singleton et
on est sr que, pour chacune de ces classes, un seul objet sera cr.

Contrler les types passs notre fonction


Vous lavez dj observ dans Python : aucun contrle nest fait sur le type des donnes
passes en paramtres de nos fonctions. Certaines, comme print, acceptent nimporte
quel type. Dautres lvent des exceptions quand un paramtre dun type incorrect leur
est fourni.
Il pourrait tre utile de coder un dcorateur qui vrifie les types passs en paramtres
notre fonction et qui lve une exception si les types attendus ne correspondent pas
ceux reus lors de lappel la fonction.
Voici notre dfinition de fonction, pour vous donner une ide :
1
2

@controler_types ( int , int )


def intervalle ( base_inf , base_sup ) :

Notre dcorateur controler_types doit sassurer qu chaque fois quon appelle la


fonction intervalle, ce sont des entiers qui sont passs en paramtres en tant que
base_inf et base_sup.
Ce dcorateur est plus complexe, bien que jaie simplifi au maximum lexemple de la
PEP 318.
Encore une fois, sil est un peu long crire, il est dune simplicit enfantine utiliser.
Code de lexemple
1
2
3
4
5

def controler_types (* a_args , ** a_kwargs ) :


""" On attend en param tres du d corateur les types souhait
s . On accepte
une liste de param tres ind termin s , tant donn que notre
fonction
d finie pourra tre appel e avec un nombre variable de
param tres et que
chacun doit tre contr l """

6
7
8
9
10

def decorateur ( fonction_a_executer ) :


""" Notre d corateur . Il doit renvoyer fonction_modifiee
"""
def fonction_modifiee (* args , ** kwargs ) :
""" Notre fonction modifi e . Elle se charge de contr
ler

269

CHAPITRE 24. LES DCORATEURS


les types qu ' on lui passe en param tres """

11
12

# La liste des param tres attendus ( a_args ) doit


tre de m me
# Longueur que celle re ue ( args )
if len ( a_args ) != len ( args ) :
raise TypeError ( " le nombre d ' arguments attendu
n ' est pas gal " \
" au nombre re u " )
# On parcourt la liste des arguments re us et non
nomm s
for i , arg in enumerate ( args ) :
if a_args [ i ] is not type ( args [ i ]) :
raise TypeError ( " l ' argument { 0 } n ' est pas
du type " \
" { 1 } " . format (i , a_args [ i ]) )

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# On parcourt pr sent la liste des param tres re


us et nomm s
for cle in kwargs :
if cle not in a_kwargs :
raise TypeError ( " l ' argument { 0 } n 'a aucun
type " \
" pr cis " . format ( repr ( cle ) ) )
if a_kwargs [ cle ] is not type ( kwargs [ cle ]) :
raise TypeError ( " l ' argument { 0 } n ' est pas
de type " \
" { 1 } " . format ( repr ( cle ) , a_kwargs [
cle ]) )
return fonction_a_executer (* args , ** kwargs )
return fonction_modifiee
return decorateur

Explications
Cest un dcorateur assez complexe (et pourtant, croyez-moi, je lai simplifi autant
que possible). Nous allons dabord voir comment lutiliser :
1
2
3
4
5
6
7
8
9
10
11

270

>>> @controler_types ( int , int )


... def intervalle ( base_inf , base_sup ) :
...
print (" Intervalle de {0} {1}". format ( base_inf ,
base_sup ) )
...
>>> intervalle (1 , 8)
Intervalle de 1 8
>>> intervalle (5 , " oups !")
Traceback ( most recent call last ) :
File " < stdin >" , line 1 , in < module >
File " < stdin >" , line 24 , in fonction_modifiee
TypeError : l argument 1 n est pas du type < class int >

EXEMPLES DAPPLICATIONS
12

>>>

L encore, lutilisation est des plus simples. Intressons-nous au dcorateur proprement


dit, cest dj un peu plus complexe.
Notre dcorateur doit prendre des paramtres (une liste de paramtres indtermins
dailleurs, car notre fonction doit elle aussi prendre une liste de paramtres indtermins et lon doit contrler chacun deux). On dfinit donc un paramtre a_args qui
contient la liste des types des paramtres non nomms attendus, et un second paramtre
a_kwargs qui contient le dictionnaire des types des paramtres nomms attendus.
Vous suivez toujours ?
Vous devriez comprendre la construction densemble, nous lavons vue un peu plus
haut. Elle comprend trois niveaux, puisque nous devons influer sur le comportement
de la fonction et que notre dcorateur prend des paramtres. Notre code de contrle se
trouve, comme il se doit, dans notre fonction fonction_modifiee (qui va prendre la
place de notre fonction_a_executer).
On commence par vrifier que la liste des paramtres non nomms attendus est bien
gale en taille la liste des paramtres non nomms reus. On vrifie ensuite individuellement chaque paramtre reu, en contrlant son type. Si le type reu est gal
au type attendu, tout va bien. Sinon, on lve une exception. On rpte lopration
sur les paramtres nomms (avec une petite diffrence, puisquil sagit de paramtres
nomms : ils sont contenus dans un dictionnaire, pas une liste).
Si tout va bien (aucune exception na t leve), on excute notre fonction en renvoyant
son rsultat.
Voil nos exemples dapplications. Il y en a bien dautres, vous pouvez en retrouver
plusieurs sur la PEP 318 consacre aux dcorateurs, ainsi que des informations supplmentaires : nhsitez pas y faire un petit tour.

En rsum
Les dcorateurs permettent de modifier le comportement dune fonction.
Ce sont eux-mmes des fonctions, prenant en paramtre une fonction et renvoyant
une fonction (qui peut tre la mme).
On peut dclarer une fonction comme dcore en plaant, au-dessus de la ligne de
sa dfinition, la ligne @nom_decorateur.
Au moment de la dfinition de la fonction, le dcorateur est appel et la fonction
quil renvoie sera celle utilise.
Les dcorateurs peuvent galement prendre des paramtres pour influer sur le comportement de la fonction dcore.

271

CHAPITRE 24. LES DCORATEURS

272

Chapitre

25

Les mtaclasses
Difficult :
oujours plus loin vers la mtaprogrammation ! Nous allons ici nous intresser au
concept des mtaclasses, ou comment gnrer des classes partir. . . dautres classes !
Je ne vous cache pas quil sagit dun concept assez avanc de la programmation
Python, prenez donc le temps ncessaire pour comprendre ce nouveau concept.

273

CHAPITRE 25. LES MTACLASSES

Retour sur le processus dinstanciation


Depuis la troisime partie de ce cours, nous avons cr bon nombre dobjets. Nous avons
dcouvert au dbut de cette partie le constructeur, cette mthode appele quand on
souhaite crer un objet.
Je vous ai dit alors que les choses taient un peu plus complexes que ce quil semblait.
Nous allons maintenant voir en quoi !
Admettons que vous ayez dfini une classe :
class Personne :

1
2

""" Classe d finissant une personne .

3
4

Elle poss de comme attributs :


nom -- le nom de la personne
prenom -- son pr nom
age -- son ge
lieu_residence -- son lieu de r sidence

5
6
7
8
9
10

Le nom et le pr nom doivent tre pass s au constructeur . """

11
12

def __init__ ( self , nom , prenom ) :


""" Constructeur de notre personne . """
self . nom = nom
self . prenom = prenom
self . age = 23
self . lieu_residence = " Lyon "

13
14
15
16
17
18

Cette syntaxe na rien de nouveau pour nous.


Maintenant, que se passe-t-il quand on souhaite crer une personne ? Facile, on rdige
le code suivant :
personne = Personne ( " Doe " , " John " )

Lorsque lon excute cela, Python appelle notre constructeur __init__ en lui transmettant les arguments fournis la construction de lobjet. Il y a cependant une tape
intermdiaire.
Si vous examinez la dfinition de notre constructeur :
1

def __init__ ( self , nom , prenom ) :

Vous ne remarquez rien dtrange ? Peut-tre pas, car vous avez t habitus cette
syntaxe depuis le dbut de cette partie : la mthode prend en premier paramtre self.
Or, self, vous vous en souvenez, cest lobjet que nous manipulons. Sauf que, quand
on cre un objet. . . on souhaite rcuprer un nouvel objet mais on nen passe aucun
la classe.
Dune faon ou dune autre, notre classe cre un nouvel objet et le passe notre
constructeur. La mthode __init__ se charge dcrire dans notre objet ses attributs,
274

RETOUR SUR LE PROCESSUS DINSTANCIATION


mais elle nest pas responsable de la cration de notre objet. Nous allons prsent voir
qui sen charge.

La mthode __new__
La mthode __init__, comme nous lavons vu, est l pour initialiser notre objet (en
crivant des attributs dedans, par exemple) mais elle nest pas l pour le crer. La
mthode qui sen charge, cest __new__.
Cest aussi une mthode spciale, vous en reconnaissez la particularit. Cest galement
une mthode dfinie par object, que lon peut redfinir en cas de besoin.
Avant de voir ce quelle prend en paramtres, voyons plus prcisment ce qui se passe
quand on tente de construire un objet :
On demande crer un objet, en crivant par exemple Personne("Doe", "John").
La mthode __new__ de notre classe (ici Personne) est appele et se charge de
construire un nouvel objet.
Si __new__ renvoie une instance de la classe, on appelle le constructeur __init__ en
lui passant en paramtres cette nouvelle instance ainsi que les arguments passs lors
de la cration de lobjet.
Maintenant, intressons-nous la structure de notre mthode __new__.
Cest une mthode de classe, ce qui signifie quelle ne prend pas self en paramtre.
Cest logique, dailleurs : son but est de crer une nouvelle instance de classe, linstance
nexiste pas encore.
Elle ne prend donc pas self en premier paramtre (linstance dobjet). Cependant, elle
prend la classe manipule cls.
Autrement dit, quand on souhaite crer un objet de la classe Personne, la mthode
__new__ de la classe Personne est appele et prend comme premier paramtre la classe
Personne elle-mme.
Les autres paramtres passs la mthode __new__ seront transmis au constructeur.
Voyons un peu cela, exprim sous forme de code :
1

class Personne :

2
3

""" Classe d finissant une personne .

4
5
6
7
8
9

Elle poss de comme attributs :


nom -- le nom de la personne
prenom -- son pr nom
age -- son ge
lieu_residence -- son lieu de r sidence

10
11

Le nom et le pr nom doivent tre pass s au constructeur . """

12
13
14

def __new__ ( cls , nom , prenom ) :


print ( " Appel de la m thode __new__ de la classe { } " .

275

CHAPITRE 25. LES MTACLASSES

15
16

format ( cls ) )
# On laisse le travail object
return object . __new__ ( cls , nom , prenom )

17
18
19
20
21
22
23
24

def __init__ ( self , nom , prenom ) :


""" Constructeur de notre personne . """
print ( " Appel de la m thode __init__ " )
self . nom = nom
self . prenom = prenom
self . age = 23
self . lieu_residence = " Lyon "

Essayons de crer une personne :


1
2
3
4

>>> personne = Personne (" Doe " , " John ")


Appel de la m thode __new__ de la classe < class __main__ .
Personne >
Appel de la m thode __init__
>>>

Redfinir __new__ peut permettre, par exemple, de crer une instance dune autre
classe. Elle est principalement utilise par Python pour produire des types immuables
(en anglais, immutable), que lon ne peut modifier, comme le sont les chanes de caractres, les tuples, les entiers, les flottants. . .
La mthode __new__ est parfois redfinie dans le corps dune mtaclasse. Nous allons
prsent voir de ce dont il sagit.

Crer une classe dynamiquement


Je le rpte une nouvelle fois, en Python, tout est objet. Cela veut dire que les entiers,
les flottants, les listes sont des objets, que les modules sont des objets, que les packages
sont des objets. . . mais cela veut aussi dire que les classes sont des objets !

La mthode que nous connaissons


Pour crer une classe, nous navons vu quune mthode, la plus utilise, faisant appel
au mot-cl class.
1

class MaClasse :

Vous pouvez ensuite crer des instances sur le modle de cette classe, je ne vous apprends rien.
Mais l o cela se complique, cest que les classes sont galement des objets.
276

CRER UNE CLASSE DYNAMIQUEMENT

Si les classes sont des objets. . . cela veut dire que les classes sont elles-mmes
modeles sur des classes ?
Eh oui. Les classes, comme tout objet, sont modeles sur une classe. Cela parat assez difficile comprendre au dbut. Peut-tre cet extrait de code vous aidera-t-il
comprendre lide.
1
2
3
4
5
6
7
8
9
10
11
12
13

>>> type (5)


< class int >
>>> type (" une cha ne ")
< class str >
>>> type ([1 , 2 , 3])
< class list >
>>> type ( int )
< class type >
>>> type ( str )
< class type >
>>> type ( list )
< class type >
>>>

On demande le type dun entier et Python nous rpond class int. Sans surprise. Mais
si on lui demande la classe de int, Python nous rpond class type.
En fait, par dfaut, toutes nos classes sont modeles sur la classe type. Cela signifie
que :
1. quand on cre une nouvelle classe (class Personne: par exemple), Python appelle la mthode __new__ de la classe type ;
2. une fois la classe cre, on appelle le constructeur __init__ de la classe type.
Cela semble sans doute encore obscur. Ne dsesprez pas, vous comprendrez peut-tre
un peu mieux ce dont je parle en lisant la suite. Sinon, nhsitez pas relire ce passage
et faire des tests par vous-mmes.

Crer une classe dynamiquement


Rsumons :
nous savons que les objets sont models sur des classes ;
nous savons que nos classes, tant elles-mmes des objets, sont modeles sur une
classe ;
la classe sur laquelle toutes les autres sont modeles par dfaut sappelle type.
Je vous propose dessayer de crer une classe dynamiquement, sans passer par le mot-cl
class mais par la classe type directement.
La classe type prend trois arguments pour se construire :
277

CHAPITRE 25. LES MTACLASSES


le nom de la classe crer ;
un tuple contenant les classes dont notre nouvelle classe va hriter ;
un dictionnaire contenant les attributs et mthodes de notre classe.
1
2
3
4
5
6
7
8
9
10

>>> Personne = type (" Personne " , () , {})


>>> Personne
< class __main__ . Personne >
>>> john = Personne ()
>>> dir ( john )
[ __class__ , __delattr__ , __dict__ , __doc__ , __eq__ ,
__format__ , __g
e__ , __getattribute__ , __gt__ , __hash__ , __init__ ,
__le__ , __lt__ ,
__module__ , __ne__ , __new__ , __reduce__ , __reduce_ex__
, __repr__ , _
_setattr__ , __sizeof__ , __str__ , __subclasshook__ ,
__weakref__ ]
>>>

Jai simplifi le code au maximum. Nous crons bel et bien une nouvelle classe que
nous stockons dans notre variable Personne, mais elle est vide. Elle nhrite daucune
classe et elle ne dfinit aucun attribut ni mthode de classe.
Nous allons essayer de crer deux mthodes pour notre classe :
un constructeur __init__ ;
une mthode presenter affichant le prnom et le nom de la personne.
Je vous donne ici le code auquel on peut arriver :
1
2

def creer_personne ( personne , nom , prenom ) :


""" La fonction qui jouera le r le de constructeur pour
notre classe Personne .

Elle prend en param tre , outre la personne :


nom -- son nom
prenom -- son prenom """

4
5
6
7

personne . nom = nom


personne . prenom = prenom
personne . age = 21
personne . lieu_residence = " Lyon "

8
9
10
11
12
13
14

def p re se nter_personne ( personne ) :


""" Fonction pr sentant la personne .

15

Elle affiche son pr nom et son nom """

16
17

print ( " { } { } " . format ( personne . prenom , personne . nom ) )

18
19
20
21

# Dictionnaire des m thodes


methodes = {

278

DFINITION DUNE MTACLASSE


22
23
24

" __init__ " : creer_personne ,


" presenter " : presenter_personne ,

25
26
27

# Cr ation dynamique de la classe


Personne = type ( " Personne " , () , methodes )

Avant de voir les explications, voyons les effets :


1
2
3
4
5
6
7
8
9
10

>>> john = Personne (" Doe " , " John ")


>>> john . nom
Doe
>>> john . prenom
John
>>> john . age
21
>>> john . presenter ()
John Doe
>>>

Je ne vous le cache pas, cest une fonctionnalit que vous utiliserez sans doute assez
rarement. Mais cette explication tait propos quand on sintresse aux mtaclasses.
Pour lheure, dcomposons notre code :
1. On commence par crer deux fonctions, creer_personne et presenter_personne.
Elles sont amenes devenir les mthodes __init__ et presenter de notre future classe. tant de futures mthodes dinstance, elles doivent prendre en premier
paramtre lobjet manipul.
2. On place ces deux fonctions dans un dictionnaire. En cl se trouve le nom de la
future mthode et en valeur, la fonction correspondante.
3. Enfin, on fait appel type en lui passant, en troisime paramtre, le dictionnaire
que lon vient de constituer.
Si vous essayez de mettre des attributs dans ce dictionnaire pass type, vous devez
tre conscients du fait quil sagira dattributs de classe, pas dattributs dinstance.

Dfinition dune mtaclasse


Nous avons vu que type est la mtaclasse de toutes les classes par dfaut. Cependant,
une classe peut possder une autre mtaclasse que type.
Construire une mtaclasse se fait de la mme faon que construire une classe. Les
mtaclasses hritent de type. Nous allons retrouver la structure de base des classes que
nous avons vues auparavant.
Nous allons notamment nous intresser deux mthodes que nous avons utilises dans
nos dfinitions de classes :
279

CHAPITRE 25. LES MTACLASSES


la mthode __new__, appele pour crer une classe ;
la mthode __init__, appele pour construire la classe.

La mthode __new__
Elle prend quatre paramtres :

la mtaclasse servant de base la cration de notre nouvelle classe ;


le nom de notre nouvelle classe ;
un tuple contenant les classes dont hritent notre classe crer ;
le dictionnaire des attributs et mthodes de la classe crer.

Les trois derniers paramtres, vous devriez les reconnatre : ce sont les mmes que ceux
passs type.
Voici une mthode __new__ minimaliste.
class MaMetaClasse ( type ) :

1
2

""" Exemple d ' une m taclasse . """

3
4

def __new__ ( metacls , nom , bases , dict ) :


""" Cr ation de notre classe . """
print ( " On cr e la classe { } " . format ( nom ) )
return type . __new__ ( metacls , nom , bases , dict )

5
6
7
8

Pour dire quune classe prend comme mtaclasse autre chose que type, cest dans la
ligne de la dfinition de la classe que cela se passe :
class MaClasse ( metaclass = MaMetaClasse ) :
pass

1
2

En excutant ce code, vous pouvez voir :


1

On cr e la classe MaClasse

La mthode __init__
Le constructeur dune mtaclasse prend les mmes paramtres que __new__, sauf le
premier, qui nest plus la mtaclasse servant de modle mais la classe que lon vient de
crer.
Les trois paramtres suivants restent les mmes : le nom, le tuple des classes-mres et
le dictionnaire des attributs et mthodes de classe.
Il ny a rien de trs compliqu dans le procd, lexemple ci-dessus peut tre repris en
le modifiant quelque peu pour quil sadapte la mthode __init__.
Maintenant, voyons concrtement quoi cela peut servir.
280

DFINITION DUNE MTACLASSE

Les mtaclasses en action


Comme vous pouvez vous en douter, les mtaclasses sont gnralement utilises pour
des besoins assez complexes. Lexemple le plus rpandu est une mtaclasse charge de
tracer lappel de ses mthodes. Autrement dit, ds quon appelle une mthode dun
objet, une ligne saffiche pour le signaler. Mais cet exemple est assez difficile comprendre car il fait appel la fois au concept des mtaclasses et celui des dcorateurs,
pour dcorer les mthodes traces.
Je vous propose quelque chose de plus simple. Il va de soi quil existe bien dautres
usages, dont certains complexes, des mtaclasses.
Nous allons essayer de garder nos classes cres dans un dictionnaire prenant comme
cl le nom de la classe et comme valeur la classe elle-mme.
Par exemple, dans une bibliothque destine construire des interfaces graphiques,
on trouve plusieurs widgets 1 comme des boutons, des cases cocher, des menus, des
cadres. . . Gnralement, ces objets sont des classes hritant dune classe mre commune.
En outre, lutilisateur peut, en cas de besoin, crer ses propres classes hritant des
classes de la bibliothque.
Par exemple, la classe mre de tous nos widgets sappellera Widget. De cette classe
hriteront les classes Bouton, CaseACocher, Menu, Cadre, etc. Lutilisateur de la bibliothque pourra par ailleurs en driver ses propres classes.
Le dictionnaire que lon aimerait crer se prsente comme suit :
1

2
3
4
5
6
7
8

" Widget " : Widget ,


" Bouton " : Bouton ,
" CaseACocher " : CaseACocher ,
" Menu " : Menu ,
" Cadre " : Cadre ,
...

Ce dictionnaire pourrait tre rempli manuellement chaque fois quon cre une classe
hritant de Widget mais avouez que ce ne serait pas trs pratique.
Dans ce contexte, les mtaclasses peuvent nous faciliter la vie. Vous pouvez essayer
de faire lexercice, le code nest pas trop complexe. Cela dit, tant donn quon a vu
beaucoup de choses dans ce chapitre et que les mtaclasses sont un concept plutt
avanc, je vous donne directement le code qui vous aidera peut-tre comprendre le
mcanisme :
1

trace_classes = { } # Notre dictionnaire vide

2
3

class MetaWidget ( type ) :

4
5

""" Notre m taclasse pour nos Widgets .

1. Ce sont des objets graphiques.

281

CHAPITRE 25. LES MTACLASSES


Elle h rite de type , puisque c ' est une m taclasse .
Elle va crire dans le dictionnaire trace_classes chaque
fois
qu ' une classe sera cr e , utilisant cette m taclasse
naturellement . """

7
8
9
10

def __init__ ( cls , nom , bases , dict ) :


""" Constructeur de notre m taclasse , appel quand on cr
e une classe . """
type . __init__ ( cls , nom , bases , dict )
trace_classes [ nom ] = cls

11
12
13
14

Pas trop compliqu pour lheure. Crons notre classe Widget :


class Widget ( metaclass = MetaWidget ) :

1
2

""" Classe m re de tous nos widgets . """

3
4

pass

Aprs avoir excut ce code, vous pouvez voir que notre classe Widget a bien t ajoute
dans notre dictionnaire :
1
2
3

>>> trace_classes
{ Widget : < class __main__ . Widget >}
>>>

Maintenant, construisons une nouvelle classe hritant de Widget.


1

class bouton ( Widget ) :

2
3

""" Une classe d finissant le widget bouton . """

4
5

pass

Si vous affichez de nouveau le contenu du dictionnaire, vous vous rendrez compte que la
classe Bouton a bien t ajoute. Hritant de Widget, elle reprend la mme mtaclasse
(sauf mention contraire explicite) et elle est donc ajoute au dictionnaire.
Vous pouvez toffer cet exemple, faire en sorte que laide de la classe soit galement
conserve, ou quune exception soit leve si une classe du mme nom existe dj dans
le dictionnaire.

Pour conclure
Les mtaclasses sont un concept de programmation assez avanc, puissant mais dlicat
comprendre de prime abord. Je vous invite, en cas de doute, tester par vous-mmes
ou rechercher dautres exemples, ils sont nombreux.
282

DFINITION DUNE MTACLASSE

En rsum
Le processus dinstanciation dun objet est assur par deux mthodes, __new__ et
__init__.
__new__ est charge de la cration de lobjet et prend en premier paramtre sa classe.
__init__ est charge de linitialisation des attributs de lobjet et prend en premier
paramtre lobjet prcdemment cr par __new__.
Les classes tant des objets, elles sont toutes modeles sur une classe appele mtaclasse.
moins dtre explicitement modifie, la mtaclasse de toutes les classes est type.
On peut utiliser type pour crer des classes dynamiquement.
On peut faire hriter une classe de type pour crer une nouvelle mtaclasse.
Dans le corps dune classe, pour spcifier sa mtaclasse, on exploite la syntaxe suivante : class MaClasse(metaclass=NomDeLaMetaClasse):.

283

CHAPITRE 25. LES MTACLASSES

284

Quatrime partie

Les merveilles de la bibliothque


standard

285

Chapitre

26

Les expressions rgulires


Difficult :
ans ce chapitre, je vais mattarder sur les expressions rgulires et sur le module re
qui permet de les manipuler. En quelques mots, sachez que les expressions rgulires
permettent de raliser trs rapidement et facilement des recherches sur des chanes
de caractres.

Il existe, naturellement, bien dautres modules permettant de manipuler du texte. Cest


toutefois sur celui-ci que je vais mattarder aujourdhui, tout en vous donnant les moyens
daller plus loin si vous le dsirez.

287

CHAPITRE 26. LES EXPRESSIONS RGULIRES

Que sont les expressions rgulires ?


Les expressions rgulires sont un puissant moyen de rechercher et disoler des
expressions dune chane de caractres.
Pour simplifier, imaginez que vous faites un programme qui demande un certain nombre
dinformations lutilisateur afin de les stocker dans un fichier. Lui demander son nom,
son prnom et quelques autres informations, ce nest pas bien difficile : on va utiliser
la fonction input et rcuprer le rsultat. Jusquici, rien de nouveau.
Mais si on demande lutilisateur de fournir un numro de tlphone ? Quest-ce qui
lempche de taper nimporte quoi ? Si on lui demande de fournir une adresse e-mail et
quil tape quelque chose dinvalide, par exemple je_te_donnerai_pas_mon_email ,
que va-t-il se passer si lon souhaite envoyer automatiquement un email cette personne ?
Si ce cas nest pas gr, vous risquez davoir un problme. Les expressions rgulires
sont un moyen de rechercher, disoler ou de remplacer des expressions dans une chane.
Ici, elles nous permettraient de vrifier que le numro de tlphone saisi compte bien
dix chiffres, quil commence par un 0 et quil compte ventuellement des sparateurs
tous les deux chiffres. Si ce nest pas le cas, on demande lutilisateur de le saisir
nouveau.

Quelques lments de syntaxe pour les expressions rgulires


Si vous connaissez dj les expressions rgulires et leur syntaxe, vous pouvez passer
directement la section consacre au module re. Sinon, sachez que je ne pourrai
vous prsenter que brivement les expressions rgulires. Cest un sujet trs vaste, qui
mrite un livre lui tout seul. Ne paniquez pas, toutefois, je vais vous donner quelques
exemples concrets et vous pourrez toujours trouvez des explications plus approfondies
de par le Web.

Concrtement, comment cela se prsente-t-il ?


Le module re, que nous allons dcouvrir un peu plus loin, nous permet de faire des
recherches trs prcises dans des chanes de caractres et de remplacer des lments
de nos chanes, le tout en fonction de critres particuliers. Ces critres, ce sont nos
expressions rgulires. Pour nous, elles se prsentent sous la forme de chanes de
caractres. Les expressions rgulires deviennent assez rapidement difficiles lire mais
ne vous en faites pas : nous allons y aller petit petit.

Des caractres ordinaires


Quand on forme une expression rgulire, on peut utiliser des caractres spciaux et
dautres qui ne le sont pas. Par exemple, si nous recherchons le mot chat dans notre
288

QUE SONT LES EXPRESSIONS RGULIRES ?


chane, nous pouvons crire comme expression rgulire la chane chat . Jusque l,
rien de trs compliqu.
Mais vous vous doutez bien que les expressions rgulires ne se limitent pas ce type
de recherche extrmement simple, sans quoi les mthodes find et replace de la classe
str auraient suffit.

Rechercher au dbut ou la fin de la chane


Vous pouvez rechercher au dbut de la chane en plaant en tte de votre regex 1 le
signe daccent circonflexe ^. Si, par exemple, vous voulez rechercher la syllabe cha
en dbut de votre chane, vous crirez donc lexpression ^cha. Cette expression sera
trouve dans la chane chaton mais pas dans la chane achat.
Pour matrialiser la fin de la chane, vous utiliserez le signe $. Ainsi, lexpression q$
sera trouve uniquement si votre chane se termine par la lettre q minuscule.

Contrler le nombre doccurences


Les caractres spciaux que nous allons dcouvrir permettent de contrler le nombre
de fois o notre expression apparat dans notre chane.
Regardez lexemple ci-dessous :
1

chat *

Nous avons rajout un astrisque (*) aprs le caractre t de chat. Cela signifie que
notre lettre t pourra se retrouver 0, 1, 2, . . . fois dans notre chane. Autrement dit,
notre expression chat* sera trouve dans les chanes suivantes : chat, chaton,
chateau, herbe chat, chapeau, chatterton, chattttttttt. . .
Regardez un un les exemples ci-dessus pour vrifier que vous les comprenez bien. On
trouvera dans chacune de ces chanes lexpression rgulire chat*. Traduite en franais,
cette expression signifie : on recherche une lettre c suivie dune lettre h suivie dune
lettre a suivie, ventuellement, dune lettre t quon peut trouver zro, une ou plusieurs
fois . Peu importe que ces lettres soient trouves au dbut, la fin ou au milieu de la
chane.
Un autre exemple ? Considrez lexpression rgulire ci-dessous et essayez de la comprendre :
1

bat * e

Cette expression est trouve dans les chanes suivantes : bateau, batteur et joan
baez.
Dans nos exemples, le signe * nagit que sur la lettre qui le prcde directement, pas
sur les autres lettres qui figurent avant ou aprs.
1. Abrviation de Regular Expression.

289

CHAPITRE 26. LES EXPRESSIONS RGULIRES


Il existe dautres signes permettant de contrler le nombre doccurences dune lettre.
Je vous ai fait un petit rcapitulatif dans le tableau suivant, en prenant des exemples
dexpressions avec les lettres a, b et c :
Signe
*
+
?

Explication
0, 1 ou plus
1 ou plus
0 ou 1

Expression
abc*
abc+
abc ?

Chanes contenant lexpression


ab, abc, abcc, abcccccc
abc, abcc, abccc
ab, abc

Vous pouvez galement contrler prcisment le nombre doccurences grce aux accolades :

E{4} : signifie 4 fois la lettre E majuscule ;


E{2,4} : signifie de 2 4 fois la lettre E majuscule ;
E{,5} : signifie de 0 5 fois la lettre E majuscule ;
E{8,} : signifie 8 fois minimum la lettre E majuscule.

Les classes de caractres


Vous pouvez prciser entre crochets plusieurs caractres ou classes de caractres. Par
exemple, si vous crivez [abcd], cela signifie : lune des lettres parmi a, b, c et d.
Pour exprimer des classes, vous pouvez utiliser le tiret - entre deux lettres. Par exemple,
lexpression [A-Z] signifie une lettre majuscule . Vous pouvez prciser plusieurs
classes ou possibilits dans votre expression. Ainsi, lexpression [A-Za-z0-9] signifie
une lettre, majuscule ou minuscule, ou un chiffre .
Vous pouvez aussi contrler loccurence des classes comme nous lavons vu juste audessus. Si vous voulez par exemple rechercher 5 lettres majuscules qui se suivent dans
une chane, votre expression sera [A-Z]{5}.

Les groupes
Je vous donne beaucoup de choses retenir et vous navez pas encore loccasion de
pratiquer. Cest le dernier point sur lequel je vais mattarder et il sera rapide : comme
je lai dit plus haut, si vous voulez par exemple contrler le nombre doccurences dun
caractre, vous ajoutez derrire un signe particulier (un astrisque, un point dinterrogation, des accolades. . .). Mais si vous voulez appliquer ce contrle doccurence
plusieurs caractres, vous allez placer ces caractres entre parenthses.
1

( cha ) {2 , 5 }

Cette expression sera vrifie pour les chanes contenant la squence cha rpte
entre deux et cinq fois. Les squences cha doivent se suivre naturellement.
Les groupes sont galement utiles pour remplacer des portions de notre chane mais
nous y reviendront plus tard, quand sera venue lheure de la pratique. . . Quoi ? Cest
lheure ? Ah bah cest parti, alors !
290

LE MODULE RE

Le module re
Le module re a t spcialement conu pour travailler avec les expressions rgulires
(Regular Expressions). Il dfinit plusieurs fonctions utiles, que nous allons dcouvrir,
ainsi que des objets propres pour modliser des expressions.

Chercher dans une chane


Nous allons pour ce faire utiliser la fonction search du module re. Bien entendu, pour
pouvoir lutiliser, il faut limporter.
1
2

>>> import re
>>>

La fonction search attend deux paramtres obligatoires : lexpression rgulire, sous la


forme dune chane, et la chane de caractres dans laquelle on recherche cette expression. Si lexpression est trouve, la fonction renvoie un objet symbolisant lexpression
recherche. Sinon, elle renvoie None.
Certains caractres spciaux dans nos expressions rgulires sont modliss
par lanti-slash \. Vous savez sans doute que Python reprsente dautres caractres avec ce symbole. Si vous crivez dans une chane \n, Python effectuera
un saut de ligne !
Pour symboliser les caractres spciaux dans les expressions rgulires, il est ncessaire
dchapper lanti-slash en le faisant prcder dun autre anti-slash. Cela veut dire que
pour crire le caractre spcial \w, vous allez devoir crire \\w.
Cest assez peu pratique et parfois gnant pour la lisibilit. Cest pourquoi je vous
conseille dutiliser un format de chane que nous navons pas vu jusqu prsent : en
plaant un r avant le dlimiteur qui ouvre notre chane, tous les caractres anti-slash
quelle contient sont chapps.
1
2
3

>>> r \ n
\\n
>>>

Si vous avez du mal voir lintrt, je vous conseille simplement de vous rappeler de
mettre un r avant dcrire des chanes contenant des expressions, comme vous allez le
voir dans les exemples que je vais vous donner.
Mais revenons notre fonction search. Nous allons mettre en pratique ce que nous
avons vu prcdemment :
1
2
3

>>> re . search ( r " abc " , " abcdef ")


< _sre . SRE_Match object at 0 x00AC1640 >
>>> re . search ( r " abc " , " abacadaeaf ")

291

CHAPITRE 26. LES EXPRESSIONS RGULIRES


4
5
6
7
8
9
10

>>> re . search ( r " abc *" , " ab ")


< _sre . SRE_Match object at 0 x00AC1800 >
>>> re . search ( r " abc *" , " abccc ")
< _sre . SRE_Match object at 0 x00AC1640 >
>>> re . search ( r " chat *" , " chateau ")
< _sre . SRE_Match object at 0 x00AC1800 >
>>>

Comme vous le voyez, si lexpression est trouve dans la chane, un objet de la classe
_sre.SRE_Match est renvoy. Si lexpression nest pas trouve, la fonction renvoie None.
Cela fait quil est extrmement facile de savoir si une expression est contenue dans une
chane :
1
2
3
4

if re . match ( expression , chaine ) is not None :


# Si l ' expression est dans la cha ne
# Ou alors , plus intuitivement
if re . match ( expression , chaine ) :

Nhsitez pas tester des syntaxes plus complexes et plus utiles. Tenez, par exemple,
comment obliger lutilisateur saisir un numro de tlphone ?
Avec le bref descriptif que je vous ai donn dans ce chapitre, vous pouvez thoriquement
y arriver. Mais cest quand mme une regex assez complexe alors je vous la donne :
prenez le temps de la dcortiquer si vous le souhaitez.
Notre regex doit vrifier quune chane est un numro de tlphone. Lutilisateur peut
saisir un numro de diffrentes faons :

0X XX XX XX XX
0X-XX-XX-XX-XX
0X.XX.XX.XX.XX
0XXXXXXXXX

Autrement dit :
le premier chiffre doit tre un 0 ;
le second chiffre, ainsi que tous ceux qui suivent (9 en tout, sans compter le 0 dorigine) doivent tre compris entre 0 et 9 ;
tous les deux chiffres, on peut avoir un dlimiteur optionnel (un tiret, un point ou
un espace).
Voici la regex que je vous propose :
1

^ 0 [0 - 9 ]([ . -]?[ 0 - 9 ] { 2 } ) { 4 } $

ARGH ! Cest illisible ton truc !

Je reconnais que cest assez peu clair. Dcomposons la formule :


Dabord, on trouve un caractre accent circonflexe ^ qui veut dire quon cherche
292

LE MODULE RE

lexpression au dbut de la chane. Vous pouvez aussi voir, la fin de la regex, le


symbole $ qui veut dire que lexpression doit tre la fin de la chane. Si lexpression
doit tre au dbut et la fin de la chane, cela signifie que la chane dans laquelle on
recherche ne doit rien contenir dautre que lexpression.
Nous avons ensuite le 0 qui veut simplement dire que le premier caractre de notre
chane doit tre un 0.
Nous avons ensuite une classe de caractre [0-9]. Cela signifie quaprs le 0, on doit
trouver un chiffre compris entre 0 et 9 (peut-tre 0, peut-tre 1, peut-tre 2. . .).
Ensuite, cela se complique. Vous avez une parenthse qui matrialise le dbut dun
groupe. Dans ce groupe, nous trouvons, dans lordre :
Dabord une classe [ .-] qui veut dire soit un espace, soit un point, soit un
tiret . Juste aprs cette classe, vous avez un signe ? qui signifie que cette classe
est optionnelle.
Aprs la dfinition de notre dlimiteur, nous trouvons une classe [0-9] qui signifie
encore une fois un chiffre entre 0 et 9 . Aprs cette classe, entre accolades, vous
pouvez voir le nombre de chiffres attendus (2).
Ce groupe, contenant un sparateur optionnel et deux chiffres, doit se retrouver
quatre fois dans notre expression (aprs la parenthse fermante, vous trouvez entre
accolades le contrle du nombre doccurences).

Si vous regardez bien nos numros de tlphone, vous vous rendez compte que notre
regex sapplique aux diffrents cas prsents. La dfinition de notre numro de tlphone
nest pas vraie pour tous les numros. Cette regex est un exemple et mme une base
pour vous permettre de saisir le concept.
Si vous voulez que lutilisateur saisisse un numro de tlphone, voici le code auquel
vous pourriez arriver :
1
2
3
4
5

import re
chaine = " "
expression = r " ^ 0 [0 - 9 ]([ . -]?[ 0 - 9 ] { 2 } ) { 4 } $ "
while re . search ( expression , chaine ) is None :
chaine = input ( " Saisissez un num ro de t l phone ( valide ) :
")

Remplacer une expression


Le remplacement est un peu plus complexe. Je ne vais pas vous montrer dexemples
rellement utiles car ils sappuient en gnral sur des expressions assez difficiles comprendre.
Pour remplacer une partie dune chane de caractres sur la base dune regex, nous
allons utiliser la fonction sub du module re.
Elle prend trois paramtres :
lexpression rechercher ;
par quoi remplacer cette expression ;
la chane dorigine.
293

CHAPITRE 26. LES EXPRESSIONS RGULIRES


Elle renvoie la chane modifie.
Des groupes numrots
Pour remplacer une partie de lexpression, on doit dabord utiliser des groupes. Si vous
vous rappelez, les groupes sont indiqus entre parenthses.
1

( a ) b ( cd )

Dans cet exemple, (a) est le premier groupe et (cd) est le second.
Lordre des groupes est important dans cet exemple. Dans notre expression de remplacement, nous pouvons appeler nos groupes grce \<numro du groupe>. Pour une
fois, on compte partir de 1.
Ce nest pas trs clair ? Regardez cet exemple simple :
1
2
3

>>> re . sub ( r "( ab ) " , r " \1 " , " abcdef ")


ab cdef
>>>

On se contente ici de remplacer ab par ab .


Je vous laccorde, on serait parvenu au mme rsultat en utilisant la mthode replace
de notre chane. Mais les expressions rgulires sont bien plus prcises que cela : vous
commencez vous en rendre compte, je pense.
Je vous laisse le soin de creuser la question, je prfre ne pas vous prsenter tout de
suite des expressions trop complexes.
Donner des noms nos groupes
Nous pouvons galement donner des noms nos groupes. Cela peut tre plus clair
que de compter sur des numros. Pour cela, il faut faire suivre la parenthse ouvrant
le groupe dun point dinterrogation, dun P majuscule et du nom du groupe entre
chevrons <>.
1

(? P < id >[ 0 - 9 ] { 2 } )

Dans lexpression de remplacement, on utilisera lexpression \g<nom du groupe> pour


symboliser le groupe. Prenons un exemple :
1
2
3
4
5
6
7
8
9

>>> texte = """


... nom = Task1 , id =8
... nom = Task2 , id =31
... nom = Task3 , id =127"""
... ...
...
>>> print ( re . sub ( r " id =(? P < id >[0 -9]+) " , r " id [\ g < id >]" , texte ) )
nom = Task1 , id [8]
nom = Task2 , id [31]

294

LE MODULE RE
10
11
12

nom = Task3 , id [127]


...
>>>

Des expressions compiles


Si, dans votre programme, vous utilisez plusieurs fois les mmes expressions rgulires,
il peut tre utile de les compiler. Le module re propose en effet de conserver votre
expression rgulire sous la forme dun objet que vous pouvez stocker dans votre programme. Si vous devez chercher cette expression dans une chane, vous passez par des
mthodes de lexpression. Cela vous fait gagner en performances si vous faites souvent
appel cette expression.
Par exemple, jai une expression qui est appele quand lutilisateur saisit son mot de
passe. Je veux vrifier que son mot de passe fait bien six caractres au minimum et quil
ne contient que des lettres majuscules, minuscules et des chiffres. Voici lexpression
laquelle jarrive :
1

^[ A - Za - z0 - 9 ] {6 , } $

chaque fois quun utilisateur saisit un mot de passe, le programme va appeler


re.search pour vrifier que celui-ci respecte bien les critres de lexpression. Il serait plus judicieux de conserver lexpression en mmoire.
On utilise pour ce faire la mthode compile du module re. On stocke la valeur renvoye
(une expression rgulire compile) dans une variable, cest un objet standard pour le
reste.
1
2

chn_mdp = r " ^[ A - Za - z0 - 9 ] {6 , } $ "


exp_mdp = re . compile ( chn_mdp )

Ensuite, vous pouvez utiliser directement cette expression compile. Elle possde plusieurs mthodes utiles, dont search et sub que nous avons vu plus haut. la diffrence
des fonctions du module re portant les mmes noms, elles ne prennent pas en premier
paramtre lexpression (celle-ci se trouve directement dans lobjet).
Voyez plutt :
1
2
3
4
5

chn_mdp = r " ^[ A - Za - z0 - 9 ] {6 , } $ "


exp_mdp = re . compile ( chn_mdp )
mot_de_passe = " "
while exp_mdp . search ( mot_de_passe ) is None :
mot_de_passe = input ( " Tapez votre mot de passe : " )

En rsum
Les expressions rgulires permettent de chercher et remplacer certaines expressions
dans des chanes de caractres.
295

CHAPITRE 26. LES EXPRESSIONS RGULIRES


Le module re de Python permet de manipuler des expressions rgulires en Python.
La fonction search du module re permet de chercher une expression dans une chane.
Pour remplacer une certaine expression dans une chane, on utilise la fonction sub
du module re.
On peut galement compiler les expressions rgulires grce la fonction compile
du module re.

296

Chapitre

27

Le temps
Difficult :
xprimer un temps en informatique, cela soulve quelques questions. Disposer dune
mesure du temps dans un programme peut avoir des applications varies : connatre la
date et lheure actuelles et faire remonter une erreur, calculer depuis combien de temps
le programme a t lanc, grer des alarmes programmes, faire des tests de performance. . .
et jen passe !

Il existe plusieurs faons de reprsenter des temps, que nous allons dcouvrir maintenant.
Pour bien suivre ce chapitre, vous aurez besoin de matriser lobjet : savoir ce quest un
objet et comment en crer un.

297

CHAPITRE 27. LE TEMPS

Le module time
Le module time est sans doute le premier tre utilis quand on souhaite manipuler
des temps de faon simple.
Notez que, dans la documentation de la bibliothque standard, ce module est class
dans la rubrique Generic Operating System Services 1 . Ce nest pas un hasard :
time est un module trs proche du systme. Cela signifie que certaines fonctions de
ce module pourront avoir des rsultats diffrents sur des systmes diffrents. Pour ma
part, je vais surtout mattarder sur les fonctionnalits les plus gnriques possibles afin
de ne perdre personne.
Je vous invite consulter les codes web suivants pour plus de documentation :


Bibliothque standard
B
Code web : 110068




Module time
B
Code web : 299481

Reprsenter une date et une heure dans un nombre unique


Comment reprsenter un temps ? Il existe, naturellement, plusieurs rponses cette
question. Celle que nous allons voir ici est sans doute la moins comprhensible pour
un humain, mais la plus adapte un ordinateur : on stocke la date et lheure dans un
seul entier.
Comment reprsenter une date et une heure dans un unique entier ?

Lide retenue a t de reprsenter une date et une heure en fonction du nombre de


secondes coules depuis une date prcise. La plupart du temps, cette date est lEpoch
Unix, le 1er janvier 1970 00 : 00 : 00.
Pourquoi cette date plutt quune autre ?

Il fallait bien choisir une date de dbut. Lanne 1970 a t considre comme un
bon dpart, compte tenu de lessor qua pris linformatique partir de cette poque.
Dautre part, un ordinateur est invitablement limit quand il traite des entiers ; dans
les langages de lpoque, il fallait tenir compte de ce fait tout simple : on ne pouvait
pas compter un nombre de secondes trop important. La date de lEpoch ne pouvait
donc pas tre trop recule dans le temps.
Nous allons voir dans un premier temps comment afficher ce fameux nombre de secondes
1. Cest--dire les services communs aux diffrents systmes dexploitation.

298

LE MODULE TIME
coules depuis le 1er janvier 1970 00 :00 :00. On utilise la fonction time du module
time.
1
2
3
4

>>> import time


>>> time . time ()
1297642146.562
>>>

Cela fait beaucoup ! Dun autre ct, songez quand mme que cela reprsente le nombre
de secondes coules depuis plus de quarante ans prsent.
Maintenant, je vous laccorde, ce nombre nest pas trs comprhensible pour un humain.
Par contre, pour un ordinateur, cest lidal : les dures calcules en nombre de secondes
sont faciles additionner, soustraire, multiplier. . . bref, lordinateur se dbrouille bien
mieux avec ce nombre de secondes, ce timestamp comme on lappelle gnralement.
Faites un petit test : stockez la valeur renvoye par time.time() dans une premire
variable, puis quelques secondes plus tard stockez la nouvelle valeur renvoye par
time.time() dans une autre variable. Comparez-les, soustrayez-les, vous verrez que
cela se fait tout seul :
1
2
3
4
5
6
7
8
9
10

>>> debut = time . time ()


>>> # On attend quelques secondes avant de taper la commande
suivante
... fin = time . time ()
>>> print ( debut , fin )
1297642195.45 1297642202.27
>>> debut < fin
True
>>> fin - debut # Combien de secondes entre debut et fin ?
6.812 00003623 9624
>>>

Vous pouvez remarquer que la valeur renvoye par time.time() nest pas un entier
mais bien un flottant. Le temps ainsi donn est plus prcis qu une seconde prs. Pour
des calculs de performance, ce nest en gnral pas cette fonction que lon utilise. Mais
cest bien suffisant la plupart du temps.

La date et lheure de faon plus prsentable


Vous allez me dire que cest bien joli davoir tous nos temps rduits des nombres
mais que ce nest pas trs lisible pour nous. Nous allons dcouvrir tout au long de ce
chapitre des moyens dafficher nos temps de faon plus lgante et dobtenir les diverses
informations relatives une date et une heure. Je vous propose ici un premier moyen :
une sortie sous la forme dun objet contenant dj beaucoup dinformations.
Nous allons utiliser la fonction localtime du module time.
1

time . localtime ()

299

CHAPITRE 27. LE TEMPS


Elle renvoie un objet contenant, dans lordre :
1. tm_year : lanne sous la forme dun entier ;
2. tm_mon : le numro du mois (entre 1 et 12) ;
3. tm_mday : le numro du jour du mois (entre 1 et 31, variant dun mois et dune
anne lautre) ;
4. tm_hour : lheure du jour (entre 0 et 23) ;
5. tm_min : le nombre de minutes (entre 0 et 59) ;
6. tm_sec : le nombre de secondes (entre 0 et 61, mme si on nutilisera ici que les
valeurs de 0 59, cest bien suffisant) ;
7. tm_wday : un entier reprsentant le jour de la semaine (entre 0 et 6, 0 correspond
par dfaut au lundi) ;
8. tm_yday : le jour de lanne, entre 1 et 366 ;
9. tm_isdst : un entier reprsentant le changement dheure local.
Comme toujours, si vous voulez en apprendre plus, je vous renvoie la documentation
officielle du module time.
Comme je lai dit plus haut, nous allons utiliser la fonction localtime. Elle prend
un paramtre optionnel : le timestamp tel que nous lavons dcouvert plus haut. Si
ce paramtre nest pas prcis, localtime utilisera automatiquement time.time() et
renverra donc la date et lheure actuelles.
1
2
3
4
5
6
7

>>> time . localtime ()


time . struct_time ( tm_year =2011 , tm_mon =2 , tm_mday =14 , tm_hour =3 ,
tm_min =22 , tm_sec =7 , tm_wday =0 , tm_yday =45 , tm_isdst =0)
>>> time . localtime ( debut )
time . struct_time ( tm_year =2011 , tm_mon =2 , tm_mday =14 , tm_hour =1 ,
tm_min =9 , tm_sec =55 , tm_wday =0 , tm_yday =45 , tm_isdst =0)
>>> time . localtime ( fin )
time . struct_time ( tm_year =2011 , tm_mon =2 , tm_mday =14 , tm_hour =1 ,
tm_min =10 , tm_sec =2 , tm_wday =0 , tm_yday =45 , tm_isdst =0)
>>>

Pour savoir quoi correspond chaque attribut de lobjet, je vous renvoie un peu plus
haut. Pour lessentiel, cest assez clair je pense. Malgr tout, la date et lheure renvoyes
ne sont pas des plus lisibles. Lavantage de les avoir sous cette forme, cest quon peut
facilement extraire une information si on a juste besoin, par exemple, de lanne et du
numro du jour.

Rcuprer un timestamp depuis une date


Je vais passer plus vite sur cette fonction car, selon toute vraisemblance, vous lutiliserez
moins souvent. Lide est, partir dune structure reprsentant les date et heure telles
que renvoyes par localtime, de rcuprer le timestamp correspondant. On utilise
pour ce faire la fonction mktime.
300

LE MODULE TIME

1
2
3
4
5
6
7
8
9

>>> print ( debut )


1297642195.45
>>> temps = time . localtime ( debut )
>>> print ( temps )
time . struct_time ( tm_year =2011 , tm_mon =2 , tm_mday =14 , tm_hour =1 ,
tm_min =9 , tm_sec =55 , tm_wday =0 , tm_yday =45 , tm_isdst =0)
>>> ts_debut = time . mktime ( temps )
>>> print ( ts_debut )
1297642195.0
>>>

Mettre en pause lexcution du programme pendant un temps


dtermin
Cest galement une fonctionnalit intressante, mme si vous nen voyez sans doute
pas lutilit de prime abord. La fonction qui nous intresse est sleep et elle prend
en paramtre un nombre de secondes qui peut tre sous la forme dun entier ou dun
flottant. Pour vous rendre compte de leffet, je vous encourage tester par vous-mmes :
1
2

>>> time . sleep (3.5) # Faire une pause pendant 3 ,5 secondes


>>>

Comme vous pouvez le voir, Python se met en pause et vous devez attendre 3,5 secondes
avant que les trois chevrons saffichent nouveau.

Formater un temps
Intressons nous maintenant la fonction strftime. Elle permet de formater une date
et heure en la reprsentant dans une chane de caractres.
Elle prend deux paramtres :
La chane de formatage (nous verrons plus bas comment la former).
Un temps optionnel tel que le renvoie localtime. Si le temps nest pas prcis, cest
la date et lheure courantes qui sont utilises par dfaut.
Pour construire notre chane de formatage, nous allons utiliser plusieurs caractres
spciaux. Python va remplacer ces caractres par leur valeur (la valeur du temps pass
en second paramtre ou du temps actuel sinon).
Exemple :
1

time . strftime ( '% Y ')

Voici un tableau rcapitulatif des quelques symboles que vous pouvez utiliser dans cette
chane :
Donc pour afficher la date telle quon y est habitu en France :
301

CHAPITRE 27. LE TEMPS


Symbole
%A
%B
%d
%H
%M
%S
%Y

Signification
Nom du jour de la semaine
Nom du mois
Jour du mois (de 01 31)
Heure (de 00 23)
Minute (entre 00 et 59)
Seconde (de 00 59)
Anne

time . strftime ( " % A % d % B % Y % H :% M :% S " )

Mais. . . cest en anglais !

Eh oui. Mais avec ce que vous savez dj et ce que vous allez voir par la suite, vous
naurez pas de difficult personnaliser tout cela !

Bien dautres fonctions


Le module time propose bien dautres fonctions. Je ne vous ai montr que celles que
jutilise le plus souvent tout en vous prsentant quelques concepts du temps utilis en
informatique. Si vous voulez aller plus loin, vous savez quoi faire. . . non ? Allez, je vous
y encourage fortement donc je vous remets le lien vers la documentation du module
time :


Module time
B
Code web : 299481

Le module datetime
Le module datetime propose plusieurs classes pour reprsenter des dates et heures.
Vous nallez rien dcouvrir dabsolument spectaculaire dans cette section mais nous
nous avanons petit petit vers une faon de grer les dates et heures qui est davantage
oriente objet.
Encore et toujours, je ne prtends pas remplacer la documentation. Je me contente
dextraire de celle-ci les informations qui me semblent les plus importantes. Je vous
encourage, l encore, jeter un coup dil du ct de la documentation du module,
que vous trouverez ladresse :


Module datetime
B
Code web : 435379


302

LE MODULE DATETIME

Reprsenter une date


Vous le reconnatrez probablement avec moi, cest bien davoir accs au temps actuel
avec une prcision dune seconde sinon plus. . . mais parfois, cette prcision est inutile.
Dans certains cas, on a juste besoin dune date, cest--dire un jour, un mois et une
anne. Il est naturellement possible dextraire cette information de notre timestamp.
Le module datetime propose une classe date, reprsentant une date, rien quune date.
Lobjet possde trois attributs :
year : lanne ;
month : le mois ;
day : le jour du mois.
Comment fait-on pour construire notre objet date ?

Il y a plusieurs faons de procder. Le constructeur de cette classe prend trois arguments


qui sont, dans lordre, lanne, le mois et le jour du mois.
1
2
3
4
5

>>> import datetime


>>> date = datetime . date (2010 , 12 , 25)
>>> print ( date )
2010 -12 -25
>>>

Il existe deux mthodes de classe qui peuvent vous intresser :


date.today() : renvoie la date daujourdhui ;
date.fromtimestamp(timestamp) : renvoie la date correspondant au timestamp
pass en argument.
Voyons en pratique :
1
2
3
4
5
6
7
8

>>> import time


>>> import datetime
>>> aujourdhui = datetime . date . today ()
>>> aujourdhui
datetime . date (2011 , 2 , 14)
>>> datetime . date . fromtimestamp ( time . time () ) # quivalent
date . today
datetime . date (2011 , 2 , 14)
>>>

Et bien entendu, vous pouvez manipuler ces dates simplement et les comparer grce
aux oprateurs usuels, je vous laisse essayer !
303

CHAPITRE 27. LE TEMPS

Reprsenter une heure


Cest moins courant mais on peut galement tre amen manipuler une heure, indpendemment de toute date. La classe time du module datetime est l pour cela.
On construit une heure avec non pas trois mais cinq paramtres, tous optionnels :

hour (0 par dfaut) : les heures, valeur comprise entre 0 et 23 ;


minute (0 par dfaut) : les minutes, valeur comprise entre 0 et 59 ;
second (0 par dfaut) : les secondes, valeur comprise entre 0 et 59 ;
microsecond (0 par dfaut) : la prcision de lheure en micro-secondes, entre 0 et
1.000.000 ;
tzinfo (None par dfaut) : linformation de fuseau horaire (je ne dtaillerai pas cette
information ici).
Cette classe est moins utilise que datetime.date mais elle peut se rvler utile dans
certains cas. Je vous laisse faire quelques tests, noubliez pas de vous reporter la
documentation du module datetime pour plus dinformations.

Reprsenter des dates et heures


Et nous y voil ! Vous nallez pas tre bien surpris par ce que nous allons aborder. Nous
avons vu une manire de reprsenter une date, une manire de reprsenter une heure,
mais on peut naturellement reprsenter une date et une heure dans le mme objet, ce
sera probablement la classe que vous utiliserez le plus souvent. Celle qui nous intresse
sappelle datetime, comme son module.
Elle prend dabord les paramtres de datetime.date (anne, mois, jour) et ensuite
les paramtres de datetime.time (heures, minutes, secondes, micro-secondes et fuseau
horaire).
Voyons ds prsent les deux mthodes de classe que vous utiliserez le plus souvent :
datetime.now() : renvoie lobjet datetime avec la date et lheure actuelles ;
datetime.fromtimestamp(timestamp) : renvoie la date et lheure dun timestamp
prcis.
1
2
3
4

>>> import datetime


>>> datetime . datetime . now ()
datetime . datetime (2011 , 2 , 14 , 5 , 8 , 22 , 359000)
>>>

Il y a bien dautres choses voir dans ce module datetime. Si vous tes curieux ou
que vous avez des besoins plus spcifiques, que je naborde pas ici, rfrez-vous la
documentation officielle du module.

En rsum
Le module time permet, entre autres, dobtenir la date et lheure de votre systme.
304

LE MODULE DATETIME
La fonction time du module time renvoie le timestamp actuel.
La mthode localtime du module time renvoie un objet isolant les informations
dun timestamp (la date et lheure).
Le module datetime permet de reprsenter des dates et heures.
Les classes date, time et datetime permettent respectivement de reprsenter des
dates, des heures, ainsi que des ensembles date et heure .

305

CHAPITRE 27. LE TEMPS

306

Chapitre

28

Un peu de programmation systme


Difficult :
ans ce chapitre, nous allons dcouvrir plusieurs modules et fonctionnalits utiles pour
interagir avec le systme. Python peut servir crer bien des choses, des jeux, des
interfaces, mais il peut aussi faire des scripts systmes et, dans ce chapitre, nous
allons voir comment.

Les concepts que je vais prsenter ici risquent dtre plus familiers aux utilisateurs de
Linux. Toutefois, pas de panique si vous tes sur Windows : je vais prendre le temps de
vous expliquer chaque fois tout le ncessaire.

307

CHAPITRE 28. UN PEU DE PROGRAMMATION SYSTME

Les flux standard


Pour commencer, nous allons voir comment accder aux flux standard (entre standard
et sortie standard) et de quelle faon nous devons les manipuler.

quoi cela ressemble-t-il ?

Vous vous tes srement habitus, quand vous utilisez la fonction print, ce quun
message saffiche sur votre cran. Je pense que cela vous parat mme assez logique
prsent.
Sauf que, comme pour la plupart de nos manipulations en informatique, le mcanisme
qui se cache derrire nos fonctions est plus complexe et puissant quil y parat. Sachez
que vous pourriez trs bien faire en sorte quen utilisant print, le texte scrive dans
un fichier plutt qu lcran.
Quel intrt ? print est fait pour afficher lcran non ?

Pas seulement, non. Mais nous verrons cela un peu plus loin. Pour linstant, voil ce
que lon peut dire : quand vous appelez la fonction print, si le message saffiche
lcran, cest parce que la sortie standard de votre programme est redirige vers votre
cran.
On distingue trois flux standard :
Lentre standard : elle est appele quand vous utilisez input. Cest elle qui est
utilise pour demander des informations lutilisateur. Par dfaut, lentre standard
est votre clavier.
La sortie standard : comme on la vu, cest elle qui est utilise pour afficher des
messages. Par dfaut, elle redirige vers lcran.
Lerreur standard : elle est notamment utilise quand Python vous affiche le
traceback dune exception. Par dfaut, elle redirige galement vers votre cran.

Accder aux flux standard


On peut accder aux objets reprsentant ces flux standard grce au module sys qui
propose plusieurs fonctions et variables permettant dinteragir avec le systme. Nous
en reparlerons un peu plus loin dans ce chapitre, dailleurs.
1
2
3
4
5

>>> import sys


>>> sys . stdin # L entr e standard ( standard input )
< _io . TextIOWrapper name = < stdin > encoding = cp850 >
>>> sys . stdout # La sortie standard ( standard output )
< _io . TextIOWrapper name = < stdout > encoding = cp850 >

308

LES FLUX STANDARD


6
7
8

>>> sys . stderr # L erreur standard ( standard error )


< _io . TextIOWrapper name = < stderr > encoding = cp850 >
>>>

Ces objets ne vous rappellent rien ? Vraiment ?


Ils sont de la mme classe que les fichiers ouverts grce la fonction open. Et il ny a
aucun hasard derrire cela.
En effet, pour lire ou crire dans les flux standard, on utilise les mthodes read et
write.
Naturellement, lentre standard stdin peut lire (mthode read) et les deux sorties
stdout et stderr peuvent crire (mthode write).
Essayons quelque chose :
1
2
3

>>> sys . stdout . write (" un test ")


un test7
>>>

Pas trop de surprise, sauf que ce serait mieux avec un saut de ligne la fin. L, ce
que renvoie la mthode (le nombre de caractres crits) est affich juste aprs notre
message.
1
2
3
4

>>> sys . stdout . write (" Un test \ n ")


Un test
8
>>>

Modifier les flux standard


Vous pouvez modifier sys.stdin, sys.stdout et sys.stderr. Faisons un premier test :
1
2
3
4

>>> fichier = open ( sortie . txt , w )


>>> sys . stdout = fichier
>>> print (" Quelque chose ... ")
>>>

Ici, rien ne saffiche lcran. En revanche, si vous ouvrez le fichier sortie.txt, vous
verrez le message que vous avez pass print.
Je ne trouve pas le fichier sortie.txt, o est-il ?

Il doit se trouver dans le rpertoire courant de Python. Pour connatre lemplacement


de ce rpertoire, utilisez le module os et la fonction getcwd 1 .
1. Get Current Working Directory

309

CHAPITRE 28. UN PEU DE PROGRAMMATION SYSTME


Une petite subtilit : si vous essayez de faire appel getcwd directement, le rsultat
ne va pas safficher lcran. . . il va tre crit dans le fichier. Pour rtablir lancienne
sortie standard, tapez la ligne :
1

sys . stdout = sys . __stdout__

Vous pouvez ensuite faire appel la fonction getcwd :


1
2

import os
os . getcwd ()

Dans ce rpertoire, vous devriez trouver votre fichier sortie.txt.


Si vous avez modifi les flux standard et que vous cherchez les objets dorigine, ceux
redirigeant vers le clavier (pour lentre) et vers lcran (pour les sorties), vous pouvez
les trouver dans sys.__stdin__, sys.__stdout__ et sys.__stderr__.
La documentation de Python nous conseille malgr tout de garder de prfrence les
objets dorigine sous la main plutt que daller les chercher dans sys.__stdin__,
sys.__stdout__ et sys.__stderr__.
Voil qui conclut notre bref aperu des flux standard. L encore, si vous ne voyez pas
dapplication pratique ce que je viens de vous montrer, cela viendra certainement par
la suite.

Les signaux
Les signaux sont un des moyens dont dispose le systme pour communiquer avec votre
programme. Typiquement, si le systme doit arrter votre programme, il va lui envoyer
un signal.
Les signaux peuvent tre intercepts dans votre programme. Cela vous permet de dclencher une certaine action si le programme doit se fermer (enregistrer des objets dans
des fichiers, fermer les connexions rseau tablies avec des clients ventuels, . . .).
Les signaux sont galement utiliss pour faire communiquer des programmes entre eux.
Si votre programme est dcompos en plusieurs programmes sexcutant indpendamment les uns des autres, cela permet de les synchroniser certains moments cls. Nous
ne verrons pas cette dernire fonctionnalit ici, elle mriterait un cours elle seule tant
il y aurait de choses dire !

Les diffrents signaux


Le systme dispose de plusieurs signaux gnriques quil peut envoyer aux programmes
quand cela est ncessaire. Si vous demandez larrt du programme, un signal particulier
lui sera envoy.
Tous les signaux ne se retrouvent pas sur tous les systmes dexploitation, cest pourquoi
je vais surtout mattacher un signal : le signal SIGINT envoy larrt du programme.
310

LES SIGNAUX
Pour plus dinformations, un petit dtour par la documentation simpose, notamment
du ct du module signal. Vous pouvez y accder avec le code web suivant :


Module signal
B
Code web : 699981

Intercepter un signal
Commencez par importer le module signal.
1

import signal

Le signal qui nous intresse, comme je lai dit, se nomme SIGINT.


1
2
3

>>> signal . SIGINT


2
>>>

Pour intercepter ce signal, il va falloir crer une fonction qui sera appele si le signal
est envoy. Cette fonction prend deux paramtres :
le signal (plusieurs signaux peuvent tre envoys la mme fonction) ;
le frame qui ne nous intresse pas ici.
Cette fonction, cest vous de la crer. Ensuite, il faudra la connecter avec le signal
SIGINT.
Dabord, crons notre fonction :
1

import sys

2
3
4
5
6

def fermer_programme ( signal , frame ) :


""" Fonction appel e quand vient l ' heure de fermer notre
programme """
print ( " C ' est l ' heure de la fermeture ! " )
sys . exit ( 0 )

Cest quoi, la dernire ligne ?

On demande simplement notre programme Python de se fermer. Cest le comportement standard quand on rceptionne un tel signal et notre programme doit bien
sarrter un moment ou un autre.
Pour ce faire, on utilise la fonction exit (sortir, en anglais) du module sys. Elle prend
en paramtre le code de retour du programme.
Pour simplifier, la plupart du temps, si votre programme renvoie 0, le systme comprendra que tout sest bien pass. Si cest un entier autre que 0, le systme interprtera
cela comme une erreur ayant eu lieu pendant lexcution de votre programme.
311

CHAPITRE 28. UN PEU DE PROGRAMMATION SYSTME


Ici, notre programme sarrte normalement, on passe donc exit 0.
Connectons prsent notre fonction au signal SIGINT, sans quoi notre fonction ne
serait jamais appele.
On utilise pour cela la fonction signal. Elle prend en paramtre :
le signal intercepter ;
la fonction que lon doit connecter ce signal.
signal . signal ( signal . SIGINT , fermer_programme )

Ne mettez pas les parenthses la fin du nom de la fonction. On envoie la rfrence


vers la fonction, on ne lexcute pas.
Cette ligne va connecter le signal SIGINT la fonction fermer_programme que vous
avez dfinie plus haut. Ds que le systme enverra ce signal pour fermer le programme,
la fonction fermer_programme sera appele.
Pour vrifier que tout fonctionne bien, lancez une boucle infinie dans votre programme :
print ( " Le programme va boucler ... " )
while True : # Boucle infinie , True est toujours vrai
continue

1
2
3

Je vous remets le code en entier, si cela vous rend les choses plus claires :
import signal
import sys

1
2
3
4
5
6
7

def fermer_programme ( signal , frame ) :


""" Fonction appel e quand vient l ' heure de fermer notre
programme """
print ( " C ' est l ' heure de la fermeture ! " )
sys . exit ( 0 )

8
9
10

# Connexion du signal notre fonction


signal . signal ( signal . SIGINT , fermer_programme )

11
12
13
14
15

# Notre programme ...


print ( " Le programme va boucler ... " )
while True :
continue

Quand vous lancez ce programme, vous voyez un message vous informant que le programme va boucler. . . et le programme continue de tourner. Il ne sarrte pas. Il ne fait
rien, il boucle simplement mais il va continuer de boucler tant que son excution nest
pas interrompue.




Dans la fentre du programme, tapez CTRL + C sur Windows ou Linux, Cmd + C 
sur Mac OS X.
Cette combinaison de touches va demander au programme de sarrter. Aprs lavoir
saisie, vous pouvez constater queffectivement, votre fonction fermer_programme est
bien appele et soccupe de fermer le programme correctement.
312

INTERPRTER LES ARGUMENTS DE LA LIGNE DE COMMANDE


Voil pour les signaux. Si vous voulez aller plus loin, la documentation est accessible
avec le code web indiqu prcdemment :


Module signal
B
Code web : 699981

Interprter les arguments de la ligne de commande


Python nous offre plusieurs moyens, en fonction de nos besoins, pour interprter les
arguments de la ligne de commande. Pour faire court, ces arguments peuvent tre des
paramtres que vous passez au lancement de votre programme et qui influeront sur son
excution.
Ceux qui travaillent sur Linux nauront, je pense, aucun mal me suivre. Mais je vais
faire une petite prsentation pour ceux qui viennent de Windows, afin quils puissent
suivre sans difficult.
Si vous tes allergiques la console, passez la suite.

Accder la console de Windows


Il existe plusieurs moyens daccder la console de Windows. Celui que jutilise et que
je vais vous montrer passe par le Menu Dmarrer.
Ouvrez le Menu Dmarrer et
 cliquez sur excuter.... Dans la fentre qui souvre,
tapez cmd puis appuyez sur Entre .
Vous devriez vous retrouver dans une fentre en console, vous donnant plusieurs informations propres au systme.
1
2
3
4

C :\ WINDOWS \ system32 \ cmd . exe


Microsoft Windows XP [ version 5.1.2600]
( C ) Copyright 1985 -2001 Microsoft Corp .
C :\ Documents and Settings \ utilisateur >

Ce qui nous intresse, cest la dernire ligne. Cest un chemin qui vous indique quel
endroit de larborescence vous vous trouvez. Il y a toutes les chances que ce chemin
soit le rpertoire utilisateur de votre compte.
1

C :\ Documents and Settings \ utilisateur >

Nous allons commencer par nous dplacer dans le rpertoire contenant linterprteur
Python. L encore, si vous navez rien chang lors de linstallation de Python, le chemin
correspondant est C:\pythonXY, XY reprsentant les deux premiers chiffres de votre
version de Python. Avec Python 3.4, ce sera donc probablement C:\python34.
Dplacez-vous dans ce rpertoire grce la commande cd.
1

C :\ Documents and Settings \ utilisateur > cd C :\ python34

313

CHAPITRE 28. UN PEU DE PROGRAMMATION SYSTME


2

C :\ Python34 >

Si tout se passe bien, la dernire ligne vous indique que vous tes bien dans le rpertoire
Python.
En vrit, vous pouvez appeler Python de nimporte o dans larborescence mais ce
sera plus simple si nous sommes dans le rpertoire de Python pour commencer.

Accder aux arguments de la ligne de commande


Nous allons une fois encore faire appel notre module sys. Cette fois, nous allons nous
intresser sa variable argv.
Crez un nouveau fichier Python. Sur Windows, prenez bien soin de lenregistrer dans
le rpertoire de Python (C:\python34 sous Python 3.4).
Placez-y le code suivant :
import sys
print ( sys . argv )

1
2

sys.argv contient une liste des arguments que vous passez en ligne de commande, au
moment de lancer le programme. Essayez donc dappeler votre programme depuis la
ligne de commande en lui passant des arguments.
Sur Windows :
1
2
3
4
5
6
7

C :\ Python34 > python test_console . py


[ test_console . py ]
C :\ Python34 > python test_console . py arguments
[ test_console . py , arguments ]
C :\ Python34 > python test_console . py argument1 argument2
argument3
[ test_console . py , argument1 , argument2 , argument3 ]
C :\ Python34 >

Comme vous le voyez, le premier lment de sys.argv contient le nom du programme,


de la faon dont vous lavez appel. Le reste de la liste contient vos arguments (sil y
en a).
Note : vous pouvez trs bien avoir des arguments contenant des espaces. Dans ce cas,
vous devez alors encadrer largument de guillemets :
1
2
3

C :\ Python34 > python test_console . py " un argument avec des


espaces "
[ test_console . py , un argument avec des espaces ]
C :\ Python34 >

314

INTERPRTER LES ARGUMENTS DE LA LIGNE DE COMMANDE

Interprter les arguments de la ligne de commande


Accder aux arguments, cest bien, mais les interprter peut tre utile aussi.
Des actions simples
Parfois, votre programme devra dclencher plusieurs actions en fonction du premier
paramtre fourni. Par exemple, en premier argument, vous pourriez prciser lune des
valeurs suivantes : start pour dmarrer une opration, stop pour larrter, restart
pour la redmarrer, status pour connatre son tat. . . bref, les utilisateurs de Linux
ont srement bien plus dexemples lesprit.
Dans ce cas de figure, il nest pas vraiment ncessaire dinterprter les arguments de
la ligne de commande, comme on va le voir. Notre programme Python ressemblerait
simplement cela :
1

import sys

2
3
4
5

if len ( sys . argv ) < 2 :


print ( " Pr cisez une action en param tre " )
sys . exit ( 1 )

6
7

action = sys . argv [ 1 ]

8
9
10
11
12
13
14
15
16
17
18

if action == " start " :


print ( " On d marre l ' op ration " )
elif action == " stop " :
print ( " On arr te l ' op ration " )
elif action == " restart " :
print ( " On red marre l ' op ration " )
elif action == " status " :
print ( " On affiche l ' tat ( d marr ou arr t ?) de l ' op
ration " )
else :
print ( " Je ne connais pas cette action " )

Il est ncessaire de passer par la ligne de commande pour tester ce programme.

Des options plus complexes


Mais la ligne de commande permet galement de transmettre des arguments plus complexes comme des options. La plupart du temps, nos options sont sous la forme :
-option_courte (une seule lettre), --option_longue, suivie dun argument ou non.
Souvent, une option courte est accessible aussi depuis une option longue.
315

CHAPITRE 28. UN PEU DE PROGRAMMATION SYSTME


Ici, mon exemple va tre tir de Linux, mais vous navez pas vraiment besoin dtre
sur Linux pour le comprendre, rassurez-vous.
La commande ls permet dafficher le contenu dun rpertoire. On peut lui passer en
paramtres plusieurs options qui influent sur ce que la commande va afficher au final.
Par exemple, pour afficher tous les fichiers (cachs ou non) du rpertoire, on utilise
loption courte a.
1
2
3

$ ls -a
. .. fichier1 . txt
$

. fichier_cache . txt

image . png

Cette option courte est accessible depuis une option longue, all. Vous arrivez donc au
mme rsultat en tapant :
1
2
3

$ ls -- all
. .. fichier1 . txt
$

. fichier_cache . txt

image . png

Pour rcapituler, nos options courtes sont prcdes dun seul tiret et composes dune
seule lettre. Les options longues sont prcdes de deux tirets et composes de plusieurs
lettres.
Certaines options attendent un argument, prciser juste aprs loption.
Par exemple (toujours sur Linux), pour afficher les premires lignes dun fichier, vous
pouvez utiliser la commande head. Si vous voulez afficher les X premires lignes dun
fichier, vous utiliserez la commande head -n X.
1
2
3
4
5
6
7

$ head -n 5 fichier . txt


ligne 1
ligne 2
ligne 3
ligne 4
ligne 5
$

Dans ce cas, loption -n attend un argument qui est le nombre de lignes afficher.
Interprter ces options grce Python
Cette petite prsentation faite, revenons Python.
Nous allons nous intresser au module argparse qui est utile, justement, pour interprter les arguments de la ligne de commande selon un certain schma. La base du
code est la suivante :
1
2
3

316

import argparse
parser = argparse . ArgumentParser ()
parser . parse_args ()

INTERPRTER LES ARGUMENTS DE LA LIGNE DE COMMANDE


1. Dabord, on importe le module argparse ;
2. on cre ensuite un argparse.ArgumentParser qui va tre utile pour configurer
nos options interprter ;
3. enfin, on appelle la mthode parse_args() sur notre parser. Cette mthode
retourne les arguments interprts. Nous allons voir comment prciser des options
dans notre parser, pour rendre les choses plus intressantes. Notez que, par dfaut,
linterprtation des arguments se fait depuis sys.argv[1:] (cest--dire la liste
des arguments sans le nom du script).
En fait, notre parser nest pas tout fait vide. Si vous excutez le script ci-dessus avec
loption help :
> python code . py -- help
usage : code . py [ - h ]
optional arguments :
-h , -- help show this help message and exit
>

Ce qui vous donne un petit aperu de comment utiliser notre programme. Laide (option
-h ou help) est gnre par dfaut. Et si vous nutilisez pas le script convenablement :
> python code . py -- inexistante
usage : code . py [ - h ]
code . py : error : unrecognized arguments : -- inexistante
>

Les messages derreurs sont en anglais, mais vous devriez pouvoir comprendre lerreur.
Ici nous avons simplement spcifi une option qui na pas t dfinie. Essayons den
dfinir une :
1
2
3
4

import argparse
parser = argparse . ArgumentParser ()
parser . add_argument ( " x " , help = " le nombre a mettre au carr " )
parser . parse_args ()

Nous avons ajout une option grce la mthode add_argument(). Elle prend plusieurs
paramtres (de nombreux paramtres optionnels, en fait) mais nous nen avons prcis
que deux ici : loption et le message daide li.
Si vous demandez laide du script :
> python code . py -- help
usage : code . py [ - h ] x
positional arguments :
x
le nombre mettre au carr

317

CHAPITRE 28. UN PEU DE PROGRAMMATION SYSTME

optional arguments :
-h , -- help show this help message and exit
>

Nous devons maintenant prciser un nombre x en paramtre. Essayons de rcuprer sa


valeur :
import argparse
parser = argparse . ArgumentParser ()
parser . add_argument ( " x " , help = " le nombre a mettre au carr " )
args = parser . parse_args ()
print ( " Vous avez pr cis X = " , args . x )

1
2
3
4
5

Pour rcuprer les options (ce que nous voudrons faire la plupart du temps), on rcupre
le retour de la mthode parse_args(). Elle retourne un objet namespace avec nos
options en attribut. Accder args.x retourne donc le nombre prcis par lutilisateur :
> python code . py 5
Vous avez pr cis X = 5
>

Dans ce contexte, on veut un nombre. . . mais lutilisateur peut entrer nimporte quoi.
Ce nest pas une bonne chose, modifions notre mthode add_argument pour que lutilisateur ne puisse entrer que des nombres :
1
2
3
4
5
6
7

import argparse
parser = argparse . ArgumentParser ()
parser . add_argument ( " x " , type = int , help = " le nombre mettre au
carr " )
args = parser . parse_args ()
x = args . x
retour = x ** 2
print ( retour )

Comme vous le voyez, la mthode add_argument est prcise ici avec un nouvel argument : type. On lui prcise int, ce qui veut dire que lon attend un nombre (lentre de
lutilisateur sera automatiquement convertie).
Vous pouvez voir aussi que notre programme fait maintenant quelque chose de concret :
> python code . py 5
25
> python code . py -8
64
> python code . py test
usage : code . py [ - h ] x

318

INTERPRTER LES ARGUMENTS DE LA LIGNE DE COMMANDE


code . py : error : argument x : invalid int value : test
>

Comme vous le voyez, la conversion marche bien, jusquau message derreur affich si
lutilisateur nentre pas un nombre.
Jusquici nous avons cr des positional arguments , qui doivent tre prciss sans
option. Voyons comment ajouter des options facultatives :
1
2
3
4
5
6

import argparse
parser = argparse . ArgumentParser ()
parser . add_argument ( " x " , type = int , help = " le nombre mettre au
carr " )
parser . add_argument ( " -v " , " -- verbose " , action = " store_true " ,
help = " augmente la verbosit " )
args = parser . parse_args ()

7
8
9
10
11
12
13

x = args . x
retour = x ** 2
if args . verbose :
print ( " { } ^ 2 = { } " . format (x , retour ) )
else :
print ( retour )

Nous avons ajout une nouvelle option : -v ou verbose. Le nom commenant par un
tiret, argparse suppose quil sagit dune option facultative, mme si cela peut tre
modifi.
Notez que lon appelle la mthode add_argument avec largument action. Laction
prcise, store_true , permet de convertir loption prcise en boolen :
Si loption est prcise, alors args.verbose vaudra True ;
si loption nest pas prcise, alors args.verbose vaudra False.
Le rsultat affich est diffrent en fonction de loption, si elle est prcise, le message
de retour est un peu plus dtaill :
> python code . py -h
usage : code . py [ - h ] [ - v ] x
positional arguments :
x
le nombre mettre au carr
optional arguments :
-h , -- help
show this help message and exit
-v , -- verbose augmente la verbosit
> python code . py 5
25
> python code . py 5 -- verbose

319

CHAPITRE 28. UN PEU DE PROGRAMMATION SYSTME


5 \ textasciicircum {} 2 = 25
> python code . py -v 5
5 \ textasciicircum {} 2 = 25
>

Vous voyez que le retour est diffrent en fonction du niveau de verbosit. Notez aussi
que le message daide intgre bien notre nouvelle option. Cest lune des raisons (il y
en a beaucoup) qui rendent lutilisation de argparse si pratique.
Nous navons vu que le tout dbut des fonctionnalits de ce module. Si vous voulez en
apprendre plus, les ressources suivantes vont bien plus loin, que ce soit le cours consacr
argparse, qui prsente les fonctionnalits les plus couramment utilises du module ou
la documentation officielle du module argparse, qui liste les fonctionnalits de manire
plus complte. Je ne vous conseille pas de lire cette documentation sans lire le cours
avant.


Cours consacr argparse
B
Code web : 290433




Documentation officielle du
B module argparse
Code web : 955510


Excuter une commande systme depuis Python


Nous allons ici nous intresser la faon dexcuter des commandes depuis Python.
Nous allons voir deux moyens, il en existe cependant dautres.
Ceux que je vais prsenter ont lavantage de fonctionner sur Windows.

La fonction system
Vous vous souvenez peut-tre de cette fonction du module os. Elle prend en paramtre
une commande excuter, affiche le rsultat de la commande et renvoie son code de
retour.
1
2

os . system ( " ls " ) # Sur Linux


os . system ( " dir " ) # Sur Windows

Vous pouvez capturer le code de retour de la commande mais vous ne pouvez pas
capturer le retour affich par la commande.
En outre, la fonction system excute un environnement particulier rien que pour votre
commande. Cela veut dire, entre autres, que system retournera tout de suite mme si
la commande tourne toujours.
En gros, si vous faites os.system( sleep 5 ), le programme ne sarrtera pas pendant cinq secondes.
320

EXCUTER UNE COMMANDE SYSTME DEPUIS PYTHON

La fonction popen
Cette fonction se trouve galement dans le module os. Elle prend galement en paramtre une commande.
Toutefois, au lieu de renvoyer le code de retour de la commande, elle renvoie un objet,
un pipe 2 qui vous permet de lire le retour de la commande.
Un exemple sur Linux :
1
2
3
4
5
6
7

>>> import os
>>> cmd = os . popen (" ls ")
>>> cmd
< os . _wrap_close object at 0 x7f81d16554d0 >
>>> cmd . read ()
fichier1 . txt \ nimage . png \n
>>>

Le fait de lire le pipe bloque le programme jusqu ce que la commande ait fini de
sexcuter.
Je vous ai dit quil existait dautres moyens. Et au-del de cela, vous avez beaucoup
dautres choses intressantes dans le module os vous permettant dinteragir avec le
systme. . . et pour cause !

En rsum
Le module sys propose trois objets permettant daccder aux flux standard : stdin,
stdout et stderr.
Le module signal permet dintercepter les signaux envoys notre programme.
Le module argparse permet dinterprter les arguments passs en console notre
programme.
Enfin, le module os possde, entre autres, plusieurs fonctions pour envoyer des commandes au systme.

2. Mot anglais pour un tuyau .

321

CHAPITRE 28. UN PEU DE PROGRAMMATION SYSTME

322

Chapitre

29

Un peu de mathmatiques
Difficult :

ans ce chapitre, nous allons dcouvrir trois modules. Je vous ai dj fait utiliser
certains de ces modules, ce sera ici loccasion de revenir dessus plus en dtail.

Le module math qui propose un bon nombre de fonctions mathmatiques.


Le module fractions, dont nous allons surtout voir la classe Fraction, permettant. . .
vous lavez devin ? De modliser des fractions.
Et enfin le module random que vous connaissez de par nos TP et que nous allons dcouvrir
plus en dtail ici.

323

CHAPITRE 29. UN PEU DE MATHMATIQUES

Pour commencer, le module math


Le module math, vous le connaissez dj : nous lavons utilis comme premier exemple
de module cr par Python. Vous avez peut-tre eu la curiosit de regarder laide du
module pour voir quelles fonctions y taient dfinies. Dans tous les cas, je fais un petit
point sur certaines de ces fonctions.
Je ne vais pas mattarder trs longtemps sur ce module en particulier car il est plus
vraisemblable que vous cherchiez une fonction prcise et que la documentation sera,
dans ce cas, plus accessible et explicite.

Fonctions usuelles
Vous vous souvenez des oprateurs +, -, *, / et % jimagine, je ne vais peut-tre pas y
revenir.
Trois fonctions pour commencer notre petit tour dhorizon :
1
2
3
4
5
6
7
8
9
10
11

>>> math . pow (5 , 2) # 5 au carr


25.0
>>> 5 ** 2 # Pratiquement identique pow (5 , 2)
25
>>> math . sqrt (25) # Racine carr e de 25 ( square root )
5.0
>>> math . exp (5) # Exponentielle
148.4 131591025766
>>> math . fabs ( -3) # Valeur absolue
3.0
>>>

Il y a bel et bien une diffrence entre loprateur ** et la fonction math.pow. La


fonction renvoie toujours un flottant alors que loprateur renvoie un entier quand cela
est possible.

Un peu de trigonomtrie
Avant de voir les fonctions usuelles en trigonomtrie, jattire votre attention sur le fait
que les angles, en Python, sont donns et renvoys en radians (rad).
Pour rappel :
1 rad = 57,29 degrs
Cela tant dit, il existe dj dans le module math les fonctions qui vont nous permettre
de convertir simplement nos angles.
1
2

math . degrees ( angle_en_radians ) # Convertit en degr s


math . radians ( angle_en_degr s ) # Convertit en radians

324

DES FRACTIONS AVEC LE MODULE FRACTIONS


Voyons maintenant quelques fonctions. Elles se nomment, sans surprise :

cos : cosinus ;
sin : sinus ;
tan : tangente ;
acos : arc cosinus ;
asin : arc sinus ;
atan : arc tangente.

Arrondir un nombre
Le module math nous propose plusieurs fonctions pour arrondir un nombre selon diffrents critres :
1
2
3
4
5
6
7

>>> math . ceil (2.3) # Renvoie le plus petit entier >= 2.3
3
>>> math . floor (5.8) # Renvoie le plus grand entier <= 5.8
5
>>> math . trunc (9.5) # Tronque 9.5
9
>>>

Quant aux constantes du module, elles ne sont pas nombreuses : math.pi naturellement,
ainsi que math.e.
Voil, ce fut rapide mais suffisant, sauf si vous cherchez quelque chose de prcis. En
ce cas, un petit tour du ct de la documentation officielle du module math simpose.
Consultez-la grce au code web suivant :


Module math
B
Code web : 197635

Des fractions avec le module fractions


Ce module propose, entre autres, de manipuler des objets modlisant des fractions.
Cest la classe Fraction du module qui nous intresse :
1

from fractions import Fraction

Crer une fraction


Le constructeur de la classe Fraction accepte plusieurs types de paramtres :
Deux entiers, le numrateur et le dnominateur (par dfaut le numrateur vaut 0 et
le dnominateur 1). Si le dnominateur est 0, une exception ZeroDivisionError est
leve.
Une autre fraction.
325

CHAPITRE 29. UN PEU DE MATHMATIQUES


Une chane sous la forme numerateur/denominateur.
>>> un_demi = Fraction (1 , 2)
>>> un_demi
Fraction (1 , 2)
>>> un_quart = Fraction ( 1/4 )
>>> un_quart
Fraction (1 , 4)
>>> autre_fraction = Fraction ( -5 , 30)
>>> autre_fraction
Fraction ( -1 , 6)
>>>

1
2
3
4
5
6
7
8
9
10

Ne peut-on pas crer des fractions depuis un flottant ?

Si, mais pas dans le constructeur. Pour crer une fraction depuis un flottant, on utilise
la mthode de classe from_float :
>>> Fraction . from_float (0.5)
Fraction (1 , 2)
>>>

1
2
3

Et pour retomber sur un flottant, rien de plus simple :


1
2
3

>>> float ( un_quart )


0.25
>>>

Manipuler les fractions


Maintenant, quel intrt davoir nos nombres sous cette forme ? Surtout pour la prcision des calculs. Les fractions que nous venons de voir acceptent naturellement les
oprateurs usuels :
1
2
3
4

>>> un_dixieme = Fraction (1 , 10)


>>> un_dixieme + un_dixieme + un_dixieme
Fraction (3 , 10)
>>>

Alors que :
1
2
3

326

>>> 0.1 + 0.1 + 0.1


0 .3 0 0 00 0 00000000004
>>>

DU PSEUDO-ALATOIRE AVEC RANDOM


Bien sr, la diffrence nest pas norme mais elle est l. Tout dpend de vos besoins en
termes de prcision.
Dautres calculs ?
1
2
3
4
5
6
7
8
9

>>> un_dixieme * un_quart


Fraction (1 , 40)
>>> un_dixieme + 5
Fraction (51 , 10)
>>> un_demi / un_quart
Fraction (2 , 1)
>>> un_quart / un_demi
Fraction (1 , 2)
>>>

Voil. Cette petite dmonstration vous suffira si ce module vous intresse. Et si elle ne
suffit pas, rendez-vous sur la documentation officielle du module fractions accessible
avec le code web suivant :


Module fractions
B
Code web : 320808

Du pseudo-alatoire avec random


Le module random, vous lavez galement utilis pendant nos TP. Nous allons voir
quelques fonctions de ce module, le tour dhorizon sera rapide !

Du pseudo-alatoire
Lordinateur est une machine puissante, capable de faire beaucoup de choses. Mais
lancer les ds nest pas son fort. Une calculatrice standard na aucune difficult
additionner, soustraire, multiplier ou diviser des nombres. Elle peut mme faire des
choses bien plus complexes. Mais, pour un ordinateur, choisir un nombre au hasard est
bien plus compliqu quil ny parat.
Ce quil faut bien comprendre, cest que derrire notre appel random.randrange par
exemple, Python va faire un vritable calcul pour trouver un nombre alatoire. De ce
fait, le nombre gnr nest pas rellement alatoire puisquun calcul identique, effectu
dans les mmes conditions, donnera le mme nombre. Cependant, les algorithmes mis
en place pour gnrer de lalatoire sont maintenant suffisamment complexes pour que
les nombres gnrs ressemblent bien une srie alatoire. Souvenez-vous toutefois que,
pour un ordinateur, le vritable hasard ne peut pas exister.

La fonction random
Cette fonction, on ne lutilisera peut-tre pas souvent de manire directe mais elle est
implicitement utilise par le module quand on fait appel randrange ou choice que
327

CHAPITRE 29. UN PEU DE MATHMATIQUES


nous verrons plus bas.
Elle gnre un nombre pseudo-alatoire compris entre 0 et 1. Ce sera donc naturellement
un flottant :
>>> import random
>>> random . random ()
0. 95 65 461 152605507
>>>

1
2
3
4

randrange et randint
La fonction randrange prend trois paramtres :
la marge infrieure de lintervalle ;
la marge suprieure de lintervalle ;
lcart entre chaque valeur de lintervalle (1 par dfaut).

Que reprsente le dernier paramtre ?

Prenons un exemple, ce sera plus simple :


random . randrange (5 , 10 , 2 )

Cette instruction va chercher gnrer un nombre alatoire entre 5 inclus et 10 non


inclus, avec un cart de 2 entre chaque valeur. Elle va donc chercher dans la liste des
valeurs [5, 7, 9].
Si vous ne prcisez pas de troisime paramtre, il vaudra 1 par dfaut (cest le comportement attendu la plupart du temps).
La fonction randint prend deux paramtres :
l encore, la marge infrieure de lintervalle ;
la marge suprieure de lintervalle, cette fois incluse.
Pour tirer au hasard un nombre entre 1 et 6, il est donc plus intuitif de faire :
random . randint (1 , 6 )

Oprations sur des squences


Nous allons voir deux fonctions : la premire, choice, renvoie au hasard un lment
dune squence passe en paramtre :
1
2
3

>>> random . choice ([ a , b , k , p , i , w , z ])


k
>>>

328

DU PSEUDO-ALATOIRE AVEC RANDOM


La seconde sappelle shuffle. Elle prend en paramtre une squence et la mlange ;
elle modifie donc la squence quon lui passe et ne renvoie rien :
1
2
3
4
5

>>> liste = [ a , b , k , p , i , w , z ]
>>> random . shuffle ( liste )
>>> liste
[ p , k , w , z , i , b , a ]
>>>

Voil. L encore, ce fut rapide mais si vous voulez aller plus loin, vous savez ou aller. . .
droit vers la documentation officielle de Python, avec le code web suivant :


Documentation random
B
Code web : 915051

En rsum
Le module math possde plusieurs fonctions et constantes mathmatiques usuelles.
Le module fractions possde le ncessaire pour manipuler des fractions, parfois
utiles pour la prcision des calculs.
Le module random permet de gnrer des nombres pseudo-alatoires.

329

CHAPITRE 29. UN PEU DE MATHMATIQUES

330

Chapitre

30

Gestion des mots de passe


Difficult :

ans ce chapitre, nous allons nous intresser aux mots de passe et la faon de les
grer en Python, cest--dire de les rceptionner et de les protger.

Nous allons dcouvrir deux modules dans ce chapitre : dabord getpass qui permet de
demander un mot de passe lutilisateur, puis hashlib qui permet de chiffrer le mot de
passe rceptionn.

331

CHAPITRE 30. GESTION DES MOTS DE PASSE

Rceptionner un mot de passe saisi par lutilisateur


Vous allez me dire, jen suis sr, quon a dj une faon de rceptionner une saisie de
lutilisateur. Cette mthode, on la vue assez tt dans le cours : il sagit naturellement
de la fonction input.
Mais input nest pas trs discrte. Si vous saisissez un mot de passe confidentiel, il
apparat de manire visible lcran, ce qui nest pas toujours souhaitable. Quand on
tape un mot de passe, cest mme rarement souhait !
Cest ici quintervient le module getpass. La fonction qui nous intresse porte le mme
nom que le module. Elle va ragir comme input, attendre une saisie de lutilisateur
et la renvoyer. Mais la diffrence dinput, elle ne va pas afficher ce que lutilisateur
saisit.
Faisons un essai :

1
2
3
4
5
6

>>> from getpass import getpass


>>> mot_de_passe = getpass ()
Password :
>>> mot_de_passe
un mot de passe
>>>

Comme vous le voyez. . . bah justement on ne voit rien ! Le mot de passe que lon
tape est invisible. Vous appuyez sur les touches de votre clavier mais
rien ne saffiche.

Cependant, vous crivez bel et bien et, quand vous appuyez sur Entre , la fonction
getpass renvoie ce que vous avez saisi.
Ici, on le stocke dans la variable mot_de_passe. Cest plus discret quinput, reconnaissezle !
Bon, il reste un dtail, mineur certes, mais un dtail quand mme : le prompt par
dfaut, cest--dire le message qui vous invite saisir votre mot de passe, est en anglais.
Heureusement, il sagit tout simplement dun paramtre facultatif de la fonction :

1
2
3

>>> mot_de_passe = getpass (" Tapez votre mot de passe : ")


Tapez votre mot de passe :
>>>

Cest mieux.
Bien entendu, tous les mots de passe que vous rceptionnerez ne viendront pas forcment dune saisie directe dun utilisateur. Mais, dans ce cas prcis, la fonction getpass
est bien utile. la fin de ce chapitre, nous verrons une utilisation complte de cette
fonction, incluant rception et chiffrement de notre mot de passe en prime, deux en un.
332

CHIFFRER UN MOT DE PASSE

Chiffrer un mot de passe


Cette fois-ci, nous allons nous intresser au module hashlib. Mais avant de vous montrer comment il fonctionne, quelques explications simposent.

Chiffrer un mot de passe ?


La premire question quon pourrait lgitimement se poser est pourquoi protger un
mot de passe ? . Je suis sr que vous pouvez trouver par vous-mmes pas mal de
rponses : il est un peu trop facile de rcuprer un mot de passe sil est stock ou
transmis en clair. Et, avec un mot de passe, on peut avoir accs beaucoup de choses :
je nai pas besoin de vous lexpliquer. Cela fait que gnralement, quand on a besoin
de stocker un mot de passe ou de le transmettre, on le chiffre.
Maintenant, quest-ce que le chiffrement ? A priori, lide est assez simple : en partant
dun mot de passe, nimporte lequel, on arrive une seconde chane de caractres,
compltement incomprhensible.

Quel intrt ?

Eh bien, si vous voyez passer, devant vos yeux, une chane de caractres comme
b47ea832576a75814e13351dcc97eaa985b9c6b7, vous ne pouvez pas vraiment deviner
le mot de passe qui se cache derrire.
Et lordinateur ne peut pas le dchiffrer si facilement que cela non plus. Bien sr, il
existe des mthodes pour dchiffrer un mot de passe mais nous ne les verrons certainement pas ici. Nous, ce que nous voulons savoir, cest comment protger nos mots de
passe, pas comment dchiffrer ceux des autres !

Comment fonctionne le chiffrement ?

Grave question. Dabord, il existe plusieurs techniques ou algorithmes de chiffrement.


Chiffrer un mot de passe avec un certain algorithme ne donne pas le mme rsultat
quavec un autre algorithme.
Ensuite, lalgorithme, quel quil soit, est assez complexe. Je serais bien incapable de
vous expliquer en dtail comment cela marche, on fait appel beaucoup de concepts
mathmatiques relativement pousss.
Mais si vous voulez faire un exercice, je vous propose quelque chose damusant qui vous
donnera une meilleure ide du chiffrement.
Commencez par numroter toutes les lettres de lalphabet (de a z) de 1 26. Reprsentez lensemble des valeurs dans un tableau, ce sera plus simple.
333

CHAPITRE 30. GESTION DES MOTS DE PASSE


A (1)
G (7)
N (14)
T (20)

B (2)
H (8)
O (15)
U (21)

C (3)
I (9)
P (16)
V (22)

D (4)
J (10)
Q (17)
W (23)

E (5)
K (11)
R (18)
X (24)

F (6)
L (12)
S (19)
Y (25)

M (13)
Z (26)

Maintenant, supposons que nous allons chercher chiffrer des prnoms. Pour cela, nous
allons baser notre exemple sur un calcul simple : dans le tableau ci-dessus, prenez la
valeur numrique de chaque lettre constituant le prnom et additionnez lensemble des
valeurs obtenues.
Par exemple, partons du prnom Eric. Quatre lettres, cela ira vite. Oubliez les accents,
les majuscules et minuscules. On a un E (5), un R (18), un I (9) et un C (3). En
ajoutant les valeurs de chaque lettre, on a donc 5 + 18 + 9 + 3, ce qui donne 35.
Conclusion : en chiffrant Eric grce notre algorithme, on obtient le nombre 35.
Cest lide derrire le chiffrement mme si, en ralit, les choses sont beaucoup plus
complexes. En outre, au lieu davoir un chiffre en sortie, on a gnralement plutt une
chane de caractres.
Mais prenez cet exemple pour vous amuser, si vous voulez. Appliquez notre algorithme
plusieurs prnoms. Si vous vous sentez dattaque, essayez de faire une fonction Python
qui prenne en paramtre notre chane et renvoie un chiffre, ce nest pas bien difficile.
Vous pouvez maintenant vous rendre compte que derrire un nombre tel que 35, il est
plutt difficile de deviner que se cache le prnom Eric !
Si vous faites le test sur les prnoms Louis et Jacques, vous vous rendrez compte. . .
quils produisent le mme rsultat, 76. En effet :
Louis = 12 + 15 + 21 + 9 + 19 = 76
Jacques = 10 + 1 + 3 + 17 + 21 + 5 + 19 = 76
Cest ce quon appelle une collision : en prenant deux chanes diffrentes, on obtient
le mme chiffrement au final.
Les algorithmes que nous allons voir dans le module hashlib essayent de minimiser,
autant que possible, les collisions. Celui que nous venons juste de voir en est plein : il
suffit de changer de place les lettres de notre prnom et nous retombons sur le mme
nombre, aprs tout.
Voil. Fin de lexercice, on va se pencher sur le module hashlib maintenant.

Chiffrer un mot de passe


On peut commencer par importer le module hashlib :
1

import hashlib

On va maintenant choisir un algorithme. Pour nous aider dans notre choix, le module
hashlib nous propose deux listes :
algorithms_guaranteed : les algorithmes garantis par Python, les mmes dune
334

CHIFFRER UN MOT DE PASSE


plateforme lautre. Si vous voulez faire des programmes portables, il est prfrable
dutiliser un de ces algorithmes :
1
2
3

>>> hashlib . algori thms_ guaran teed


{ sha1 , sha224 , sha384 , sha256 , sha512 , md5 }
>>>

algorithms_available : les algorithmes disponibles sur votre plateforme. Tous les


algorithmes garantis sy trouvent, plus quelques autres propres votre systme.
Dans ce chapitre, nous allons nous intresser sha1.
Pour commencer, nous allons crer notre objet SHA1. On va utiliser le constructeur
sha1 du module hashlib. Il prend en paramtre une chane, mais une chane de bytes
(octets).
Pour obtenir une chane de bytes depuis une chane str, on peut utiliser la mthode
encode. Je ne vais pas rentrer dans le dtail des encodages ici. Pour crire directement
une chane bytes sans passer par une chane str, vous avez une autre possibilit
consistant mettre un b minuscule avant louverture de votre chane :
1
2
3

>>> b test
b test
>>>

Gnrons notre mot de passe :


1
2
3
4

>>> mot_de_passe = hashlib . sha1 ( b " mot de passe ")


>>> mot_de_passe
< sha1 HASH object @ 0 x00BF0ED0 >
>>>

Pour obtenir le chiffrement associ cet objet, on a deux possibilits :


la mthode digest, qui renvoie un type bytes contenant notre mot de passe chiffr ;
la mthode hexdigest, qui renvoie une chane str contenant une suite de symboles
hexadcimaux (de 0 9 et de A F).
Cest cette dernire mthode que je vais montrer ici, parce quelle est prfrable pour
un stockage en fichier si les fichiers doivent transiter dune plateforme lautre.
1
2
3

>>> mot_de_passe . hexdigest ()


b 4 7 e a 8 3 2 57 6 a 75814e13351dcc97eaa985b 9c6b7
>>>

Et pour dchiffrer ce mot de passe ?

On ne le dchiffre pas. Si vous voulez savoir si le mot de passe saisi par lutilisateur
correspond au chiffrement que vous avez conserv, chiffrez le mot de passe qui vient
335

CHAPITRE 30. GESTION DES MOTS DE PASSE


dtre saisi et comparez les deux chiffrements obtenus :
1
2

import hashlib
from getpass import getpass

3
4
5

c ha i n e_ m ot_de_passe = b " azerty "


m o t _ d e _ p a sse_chiffre = hashlib . sha1 ( chaine_mot_de_passe ) .
hexdigest ()

6
7
8
9
10
11

verrouille = True
while verrouille :
entre = getpass ( " Tapez le mot de passe : " ) # azerty
# On encode la saisie pour avoir un type bytes
entre = entre . encode ()

12
13
14
15
16
17

entre_chiffre = hashlib . sha1 ( entre ) . hexdigest ()


if entre_chiffre == mot_de_passe_chiffre :
verrouille = False
else :
print ( " Mot de passe incorrect " )

18
19

print ( " Mot de passe accept ... " )

Cela me semble assez clair. Nous avons utilis lalgorithme sha1, il en existe dautres
comme vous pouvez le voir dans hashlib.algorithms_available.
Je marrte pour ma part ici ; si vous voulez aller plus loin, je vous redirige vers les
codes web suivants :


Module getpass
B
Code web : 246938




Module hashlib
B
Code web : 331371

En rsum
Pour demander lutilisateur de saisir un mot de passe, on peut utiliser le module
getpass.
La fonction getpass du module getpass fonctionne de la mme faon que input,
sauf quelle naffiche pas ce que lutilisateur saisit.
Pour chiffrer un mot de passe, on va utiliser le module hashlib.
Ce module contient en attributs les diffrents algorithmes pouvant tre utiliss pour
chiffrer nos mots de passe.

336

Chapitre

31

Le rseau
Difficult :

aste sujet que le rseau ! Si je devais faire une prsentation dtaille, ou mme parler
des rseaux en gnral, il me faudrait bien plus dun chapitre rien que pour la thorie.

Dans ce chapitre, nous allons donc apprendre faire communiquer deux applications grce
aux sockets, des objets qui permettent de connecter un client un serveur et de transmettre
des donnes de lun lautre.
Si cela ne vous met pas leau la bouche. . .

337

CHAPITRE 31. LE RSEAU

Brve prsentation du rseau


Comme je lai dit plus haut, le rseau est un sujet bien trop vaste pour que je le prsente
en un unique chapitre. On va sattacher ici comprendre comment faire communiquer
deux applications, qui peuvent tre sur la mme machine mais aussi sur des machines
distantes. Dans ce cas, elles se connectent grce au rseau local ou Internet.
Il existe plusieurs protocoles de communication en rseau. Si vous voulez, cest un
peu comme la communication orale : pour que les changes se passent correctement,
les deux (ou plus) parties en prsence doivent parler la mme langue. Nous allons ici
parler du protocole TCP.

Le protocole TCP
Lacronyme de ce protocole signifie Transmission Control Protocol, soit protocole de
contrle de transmission . Concrtement, il permet de connecter deux applications et
de leur faire changer des informations.
Ce protocole est dit orient connexion , cest--dire que les applications sont connectes pour communiquer et que lon peut tre sr, quand on envoie une information au
travers du rseau, quelle a bien t rceptionne par lautre application. Si la connexion
est rompue pour une raison quelconque, les applications doivent rtablir la connexion
pour communiquer de nouveau.
Cela vous parat peut-tre vident mais le protocole UDP 1 , par exemple, envoie des
informations au travers du rseau sans se soucier de savoir si elles seront bien rceptionnes par la cible. Ce protocole nest pas connect, une application envoie quelque
chose au travers du rseau en spcifiant une cible. Il suffit alors de prier trs fort pour
que le message soit rceptionn correctement !
Plus srieusement, ce type de protocole est utile si vous avez besoin de faire transiter
beaucoup dinformations au travers du rseau mais quune petite perte occasionnelle
dinformations nest pas trs handicapante. On trouve ce type de protocole dans des
jeux graphiques en rseau, le serveur envoyant trs frquemment des informations au
client pour quil actualise sa fentre. Cela fait beaucoup transmettre mais ce nest pas
dramatique sil y a une petite perte dinformations de temps autre puisque, quelques
millisecondes plus tard, le serveur renverra de nouveau les informations.
En attendant, cest le protocole TCP qui nous intresse. Il est un peu plus lent que
le protocole UDP mais plus sr et, pour la quantit dinformations que nous allons
transmettre, il est prfrable dtre sr des informations transmises plutt que de la
vitesse de transmission.

Clients et serveur
Dans larchitecture que nous allons voir dans ce chapitre, on trouve en gnral un
serveur et plusieurs clients. Le serveur, cest une machine qui va traiter les requtes du
1. User Datagram Protocol

338

BRVE PRSENTATION DU RSEAU


client.
Si vous accdez par exemple OpenClassrooms, cest parce que votre navigateur, faisant office de client, se connecte au serveur dOpenClassrooms. Il lui envoie un message
en lui demandant la page que vous souhaitez afficher et le serveur dOpenClassrooms,
dans sa grande bont, envoie la page demande au client.
Cette architecture est trs frquente, mme si ce nest pas la seule envisageable.
Dans les exemples que nous allons voir, nous allons crer deux applications : lapplication serveur et lapplication client. Le serveur coute donc en attendant des
connexions et les clients se connectent au serveur.

Les diffrentes tapes


Nos applications vont fonctionner selon un schma assez similaire. Voici dans lordre les
tapes du client et du serveur. Les tapes sont trs simplifies, la plupart des serveurs
peuvent communiquer avec plusieurs clients mais nous ne verrons pas cela tout de suite.
Le serveur :
1. attend une connexion de la part du client ;
2. accepte la connexion quand le client se connecte ;
3. change des informations avec le client ;
4. ferme la connexion.
Le client :
1. se connecte au serveur ;
2. change des informations avec le serveur ;
3. ferme la connexion.
Comme on la vu, le serveur peut dialoguer avec plusieurs clients : cest tout lintrt.
Si le serveur dOpenClassrooms ne pouvait dialoguer quavec un seul client la fois,
il faudrait attendre votre tour, peut-tre assez longtemps, avant davoir accs vos
pages. Et, sans serveur pouvant dialoguer avec plusieurs clients, les jeux en rseau ou
les logiciels de messagerie instantane seraient bien plus complexes.

tablir une connexion


Pour que le client se connecte au serveur, il nous faut deux informations :
Le nom dhte (host name en anglais), qui identifie une machine sur Internet ou
sur un rseau local. Les noms dhtes permettent de reprsenter des adresses IP de
faon plus claire (on a un nom comme google.fr, plus facile retenir que ladresse
IP correspondante 74.125.224.84).
339

CHAPITRE 31. LE RSEAU


Un numro de port, qui est souvent propre au type dinformation que lon va changer. Si on demande une connexion web, le navigateur va en gnral interroger le
port 80 si cest en http ou le port 443 si cest en connexion scurise (https). Le
numro de port est compris entre 0 et 65535 (il y en a donc un certain nombre !) et
les numros entre 0 et 1023 sont rservs par le systme. On peut les utiliser, mais
ce nest pas une trs bonne ide.
Pour rsumer, quand votre navigateur tente daccder OpenClassrooms, il tablit
une connexion avec le serveur dont le nom dhte est fr.openclassrooms.com sur le
port 80. Dans ce chapitre, nous allons plus volontiers travailler avec des noms dhtes
quavec des adresses IP.

Les sockets
Comme on va le voir, les sockets sont des objets qui permettent douvrir une connexion
avec une machine locale ou distante et dchanger avec elle.
Ces objets sont dfinis dans le module socket et nous allons maintenant voir comment
ils fonctionnent.

Les sockets
Commenons donc, dans la joie et la bonne humeur, par importer notre module socket.
1

import socket

Nous allons dabord crer notre serveur puis, en parallle, un client. Nous allons faire
communiquer les deux. Pour linstant, nous nous occupons du serveur.

Construire notre socket


Nous allons pour cela faire appel au constructeur socket. Dans le cas dune connexion
TCP, il prend les deux paramtres suivants, dans lordre :
socket.AF_INET : la famille dadresses, ici ce sont des adresses Internet ;
socket.SOCK_STREAM : le type du socket, SOCK_STREAM pour le protocole TCP.
1
2

>>> c o n n e xion_principale = socket . socket ( socket . AF_INET , socket


. SOCK_STREAM )
>>>

Connecter le socket
Ensuite, nous connectons notre socket. Pour une connexion serveur, qui va attendre des
connexions de clients, on utilise la mthode bind. Elle prend un paramtre : le tuple
(nom_hote, port).
340

LES SOCKETS
Attends un peu, je croyais que ctait notre client qui se connectait notre
serveur, pas linverse. . .
Oui mais, pour que notre serveur coute sur un port, il faut le configurer en consquence.
Donc, dans notre cas, le nom de lhte sera vide et le port sera celui que vous voulez,
entre 1024 et 65535.
1
2

>>> c o n n ex i o n _principale . bind (( , 12800) )


>>>

Faire couter notre socket


Bien. Notre socket est prt couter sur le port 12800 mais il ncoute pas encore.
On va avant tout lui prciser le nombre maximum de connexions quil peut recevoir
sur ce port sans les accepter. On utilise pour cela la mthode listen. On lui passe
gnralement 5 en paramtre.
Cela veut dire que notre serveur ne pourra dialoguer quavec 5 clients maximum ?
Non. Cela veut dire que si 5 clients se connectent et que le serveur naccepte aucune
de ces connexions, aucun autre client ne pourra se connecter. Mais gnralement, trs
peu de temps aprs que le client ait demand la connexion, le serveur laccepte. Vous
pouvez donc avoir bien plus de clients connects, ne vous en faites pas.
1
2

>>> c o n n ex i o n _principale . listen (5)


>>>

Accepter une connexion venant du client


Enfin, dernire tape, on va accepter une connexion. Aucune connexion ne sest encore
prsente mais la mthode accept que nous allons utiliser va bloquer le programme
tant quaucun client ne sest connect.
Il est important de noter que la mthode accept renvoie deux informations :
le socket connect qui vient de se crer, celui qui va nous permettre de dialoguer avec
notre client tout juste connect ;
un tuple reprsentant ladresse IP et le port de connexion du client.
Le port de connexion du client. . . ce nest pas le mme que celui du serveur ?

341

CHAPITRE 31. LE RSEAU


Non car votre client, en ouvrant une connexion, passe par un port dit de sortie
qui va tre choisi par le systme parmi les ports disponibles. Pour schmatiser, quand
un client se connecte un serveur, il emprunte un port (une forme de porte, si vous
voulez) puis tablit la connexion sur le port du serveur. Il y a donc deux ports dans
notre histoire mais celui quutilise le client pour ouvrir sa connexion ne va pas nous
intresser.
>>> connexion_avec_client , infos_connexion =
c o n n e x ion_principale . accept ()

Cette mthode, comme vous le voyez, bloque le programme. Elle attend quun client se
connecte. Laissons cette fentre Python ouverte et, prsent, ouvrons-en une nouvelle
pour construire notre client.

Cration du client
Commencez par construire votre socket de la mme faon :
>>> import socket
>>> c o n n e x ion _av ec _se rv eur = socket . socket ( socket . AF_INET ,
socket . SOCK_STREAM )
>>>

1
2
3

Connecter le client
Pour se connecter un serveur, on va utiliser la mthode connect. Elle prend en paramtre un tuple, comme bind, contenant le nom dhte et le numro du port identifiant
le serveur auquel on veut se connecter.
Le numro du port sur lequel on veut se connecter, vous le connaissez : cest 12800.
Vu que nos deux applications Python sont sur la mme machine, le nom dhte va tre
localhost 2 .
>>> c o n n e x ion _av ec _se rv eur . connect (( localhost , 12800) )
>>>

1
2

Et voil, notre serveur et notre client sont connects !


Si vous retournez dans la console Python abritant le serveur, vous pouvez constater que
la mthode accept ne bloque plus, puisquelle vient daccepter la connexion demande
par le client. Vous pouvez donc de nouveau saisir du code ct serveur :
1
2
3

>>> print ( infos_connexion )


( 127.0.0.1 , 2901)
>>>
2. Cest--dire la machine locale.

342

LES SOCKETS
La premire information, cest ladresse IP du client. Ici, elle vaut 127.0.0.1 cest-dire lIP de lordinateur local. Dites-vous que lhte localhost redirige vers lIP
127.0.0.1.
Le second est le port de sortie du client, qui ne nous intresse pas ici.

Faire communiquer nos sockets


Bon, maintenant, comment faire communiquer nos sockets ? Eh bien, en utilisant les
mthodes send pour envoyer et recv pour recevoir.
Les informations que vous transmettrez seront des chanes de bytes, pas des
str !
Donc ct serveur :
1
2
3

>>> c o n n e x i o n _avec_ clien t . send ( b " Je viens d accepter la


connexion ")
32
>>>

La mthode send vous renvoie le nombre de caractres envoys.


Maintenant, ct client, on va rceptionner le message que lon vient denvoyer. La
mthode recv prend en paramtre le nombre de caractres lire. Gnralement, on lui
passe la valeur 1024. Si le message est plus grand que 1024 caractres, on rcuprera
le reste aprs.
Dans la fentre Python ct client, donc :
1
2
3
4

>>> msg_recu = c on nex io n_a vec _s erv eu r . recv (1024)


>>> msg_recu
b " Je viens d accepter la connexion "
>>>

Magique, non ? Vraiment pas ? Songez que ce petit mcanisme peut servir faire communiquer des applications entre elles non seulement sur la machine locale, mais aussi
sur des machines distantes et relies par Internet.
Le client peut galement envoyer des informations au serveur et le serveur peut les
rceptionner, tout cela grce aux mthodes send et recv que nous venons de voir.

Fermer la connexion
Pour fermer la connexion, il faut appeler la mthode close de notre socket.
Ct serveur :
343

CHAPITRE 31. LE RSEAU

>>> c o n n e xion _avec _clien t . close ()


>>>

1
2

Et ct client :
>>> c o n n e x ion _av ec _se rv eur . close ()
>>>

1
2

Voil ! Je vais rcapituler en vous prsentant dans lordre un petit serveur et un client
que nous pouvons utiliser. Et pour finir, je vous montrerai une faon doptimiser un
peu notre serveur en lui permettant de grer plusieurs clients la fois.

Le serveur
Pour viter les confusions, je vous remets ici le code du serveur, lgrement amlior.
Il naccepte quun seul client (nous verrons plus bas comment en accepter plusieurs) et
il tourne jusqu recevoir du client le message fin.
chaque fois que le serveur reoit un message, il envoie en retour le message 5 / 5.
import socket

1
2
3
4

hote = ' '


port = 12800

5
6
7
8
9

c o n n e x i o n _principale = socket . socket ( socket . AF_INET , socket .


SOCK_STREAM )
c o n n e x i o n _principale . bind (( hote , port ) )
c o n n e x i o n _principale . listen ( 5 )
print ( " Le serveur coute pr sent sur le port { } " . format ( port )
)

10
11

connexion_avec_client , infos_connexion = connexion_principale .


accept ()

12
13
14
15
16
17
18
19

msg_recu = b " "


while msg_recu != b " fin " :
msg_recu = co nnexio n_ave c_clie nt . recv ( 1024 )
# L ' instruction ci - dessous peut lever une exception si le
message
# R ceptionn comporte des accents
print ( msg_recu . decode () )
c o n n e xion _avec _clien t . send ( b " 5 / 5 " )

20
21
22
23

344

print ( " Fermeture de la connexion " )


c o n n e x i o n _avec _clien t . close ()
c o n n e x i o n _principale . close ()

LE CLIENT
Voil pour le serveur. Il est minimal, vous en conviendrez, mais il est fonctionnel. Nous
verrons un peu plus loin comment lamliorer.

Le client
L encore, je vous propose le code du client pouvant interagir avec notre serveur.
Il va tenter de se connecter sur le port 12800 de la machine locale. Il demande
lutilisateur de saisir quelque chose au clavier et envoie ce quelque chose au serveur,
puis attend sa rponse.
1

import socket

2
3
4

hote = " localhost "


port = 12800

5
6
7
8

co n n e x i o n _ a v e c_ se rve ur = socket . socket ( socket . AF_INET , socket .


SOCK_STREAM )
co n n e x i o n _ a v e c_ se rve ur . connect (( hote , port ) )
print ( " Connexion tablie avec le serveur sur le port { } " . format
( port ) )

9
10
11
12
13
14
15
16
17
18

msg_a_envoyer = b " "


while msg_a_envoyer != b " fin " :
msg_a_envoyer = input ( " > " )
# Peut planter si vous tapez des caract res sp ciaux
msg_a_envoyer = msg_a_envoyer . encode ()
# On envoie le message
c o n n e x i o n _ av ec_ se rve ur . send ( msg_a_envoyer )
msg_recu = c on nex ion _a vec _s erv eur . recv ( 1024 )
print ( msg_recu . decode () ) # L encore , peut planter s ' il y a
des accents

19
20
21

print ( " Fermeture de la connexion " )


co n n e x i o n _ a v e c_ se rve ur . close ()

Que font les mthodes encode et decode ?

encode est une mthode de str. Elle peut prendre en paramtre un nom dencodage
et permet de passer un str en chane bytes. Cest, comme vous le savez, ce type
de chane que send accepte. En fait, encode encode la chane str en fonction dun
encodage prcis (par dfaut, Utf-8).
decode, linverse, est une mthode de bytes. Elle aussi peut prendre en paramtre un
encodage et elle renvoie une chane str dcode grce lencodage (par dfaut Utf-8).
Si lencodage de votre console est diffrent dUtf-8 (ce sera souvent le cas sur Windows),
345

CHAPITRE 31. LE RSEAU


des erreurs peuvent se produire si les messages que vous encodez ou dcodez comportent
des accents.
Voil, nous avons vu un serveur et un client, tous deux trs simples. Maintenant, voyons
quelque chose de plus labor !

Un serveur plus labor

Quel sont les problmes de notre serveur ?

Si vous y rflchissez, il y en a pas mal !


Dabord, notre serveur ne peut accepter quun seul client. Si dautres clients veulent
se connecter, ils ne peuvent pas.
Ensuite, on part toujours du principe quon attend le message dun client et quon
lui renvoie immdiatement aprs rception. Mais ce nest pas toujours le cas : parfois
vous envoyez un message au client alors quil ne vous a rien envoy, parfois vous
recevez des informations de sa part alors que vous ne lui avez rien envoy.
Prenez un logiciel de messagerie instantane : est-ce que, pour dialoguer, vous tes
obligs dattendre que votre interlocuteur vous rponde ? Ce nest pas jenvoie un
message, il me rpond, je lui rponds, il me rpond . . . Parfois, souvent mme, vous
enverrez deux messages la suite, peut-tre mme trois, ou linverse, qui sait ?
Bref, on doit pouvoir envoyer plusieurs messages au client et rceptionner plusieurs
messages dans un ordre inconnu. Avec notre technique, cest impossible (faites le test
si vous voulez).
En outre, les erreurs sont assez mal gres, vous en conviendrez.

Le module select
Le module select va nous permettre une chose trs intressante, savoir interroger plusieurs clients dans lattente dun message rceptionner, sans paralyser notre
programme.
Pour schmatiser, select va couter sur une liste de clients et retourner au bout dun
temps prcis. Ce que renvoie select, cest la liste des clients qui ont un message
rceptionner. Il suffit de parcourir ces clients, de lire les messages en attente (grce
recv) et le tour est jou.
Sur Linux, select peut tre utilis sur autre chose que des sockets mais, cette fonctionnalit ntant pas portable, je ne fais que la mentionner ici.
346

UN SERVEUR PLUS LABOR


En thorie
La fonction qui nous intresse porte le mme nom que le module associ, select. Elle
prend trois ou quatre arguments et en renvoie trois. Cest maintenant quil faut tre
attentif :
Les arguments que prend la fonction sont :
rlist : la liste des sockets en attente dtre lus ;
wlist : la liste des sockets en attente dtre crits ;
xlist : la liste des sockets en attente dune erreur (je ne mattarderai pas sur cette
liste) ;
timeout : le dlai pendant lequel la fonction attend avant de retourner. Si vous
prcisez en timeout 0, la fonction retourne immdiatement. Si ce paramtre nest
pas prcis, la fonction retourne ds quun des sockets change dtat (est prt tre
lu sil est dans rlist par exemple) mais pas avant.
Concrtement, nous allons surtout nous intresser au premier et au quatrime paramtre. En effet, wlist et xlist ne nous intresseront pas prsentement.
Ce quon veut, cest mettre des sockets dans une liste et que select les surveille, en
retournant ds quun socket est prt tre lu. Comme cela notre programme ne bloque
pas et il peut recevoir des messages de plusieurs clients dans un ordre compltement
inconnu.
Maintenant, concernant le timeout : comme je vous lai dit, si vous ne le prcisez pas,
select bloque jusquau moment o lun des sockets que nous coutons est prt tre
lu, dans notre cas. Si vous prcisez un timeout de 0, select retournera tout de suite.
Sinon, select retournera au bout du temps que vous indiquez en secondes, ou plus tt
si un socket est prt tre lu.
En gros, si vous prcisez un timeout de 1, la fonction va bloquer pendant une seconde maximum. Mais si un des sockets en coute est prt tre lu dans lintervalle
(cest--dire si un des clients envoie un message au serveur), la fonction retourne prmaturment.
select renvoie trois listes, l encore rlist, wlist et xlist, sauf quil ne sagit pas des
listes fournies en entre mais uniquement des sockets lire dans le cas de rlist.
Ce nest pas clair ? Considrez cette ligne (ne lessayez pas encore ) :
1

rlist , wlist , xlist = select . select ( clients_connectes , [] , [] ,


2)

Cette instruction va couter les sockets contenus dans la liste clients_connectes.


Elle retournera au plus tard dans 2 secondes. Mais elle retournera plus tt si un client
envoie un message. La liste des clients ayant envoy un message se retrouve dans notre
variable rlist. On la parcourt ensuite et on peut appeler recv sur chacun des sockets.
Si ce nest pas plus clair, rassurez-vous : nous allons voir select en action un peu plus
bas. Vous pouvez galement aller jeter un coup dil la documentation du module,
avec le code web suivant :
347

CHAPITRE 31. LE RSEAU



Module select
B
Code web : 261326

select en action
Nous allons un peu travailler sur notre serveur. Vous pouvez garder le mme client de
test.
Le but va tre de crer un serveur pouvant accepter plusieurs clients, rceptionner leurs
messages et leur envoyer une confirmation chaque rception. Lexercice ne change pas
beaucoup mais on va utiliser select pour travailler avec plusieurs clients.
Jai parl de select pour couter plusieurs clients connects mais cette fonction va
galement nous permettre de savoir si un (ou plusieurs) clients sont connects au serveur. Si vous vous souvenez, la mthode accept est aussi une fonction bloquante. On
va du reste lutiliser de la mme faon quun peu plus haut.
Je crois vous avoir donn assez dinformations thoriques. Le code doit parler maintenant :
import socket
import select

1
2
3
4
5

hote = ' '


port = 12800

6
7
8
9
10

c o n n e x i o n _principale = socket . socket ( socket . AF_INET , socket .


SOCK_STREAM )
c o n n e x i o n _principale . bind (( hote , port ) )
c o n n e x i o n _principale . listen ( 5 )
print ( " Le serveur coute pr sent sur le port { } " . format ( port )
)

11
12
13
14
15
16
17
18
19

serveur_lance = True
clien ts_connectes = []
while serveur_lance :
# On va v rifier que de nouveaux clients ne demandent pas
se connecter
# Pour cela , on coute la connexion_principale en lecture
# On attend maximum 50ms
connexions_demandees , wlist , xlist = select . select ([
c o nnexion_principale ] ,
[] , [] , 0 . 05 )

20
21
22
23
24

for connexion in connexions_demandees :


connexion_avec_client , infos_connexion = connexion .
accept ()
# On ajoute le socket connect la liste des clients
clients_connectes . append ( conn exion_ avec_ client )

25
26

348

# Maintenant , on coute la liste des clients connect s

UN SERVEUR PLUS LABOR


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

# Les clients renvoy s par select sont ceux devant tre lus
( recv )
# On attend l encore 50ms maximum
# On enferme l ' appel select . select dans un bloc try
# En effet , si la liste de clients connect s est vide , une
exception
# Peut tre lev e
clients_a_lire = []
try :
clients_a_lire , wlist , xlist = select . select (
clients_connectes ,
[] , [] , 0 . 05 )
except select . error :
pass
else :
# On parcourt la liste des clients lire
for client in clients_a_lire :
# Client est de type socket
msg_recu = client . recv ( 1024 )
# Peut planter si le message contient des caract
res sp ciaux
msg_recu = msg_recu . decode ()
print ( " Re u { } " . format ( msg_recu ) )
client . send ( b " 5 / 5 " )
if msg_recu == " fin " :
serveur_lance = False

49
50
51
52

print ( " Fermeture des connexions " )


for client in clients_connectes :
client . close ()

53
54

co n n e x i o n _p r i ncipale . close ()

Cest plus long hein ? Cest invitable, cependant.


Maintenant notre serveur peut accepter des connexions de plus dun client, vous pouvez
faire le test. En outre, il ne se bloque pas dans lattente dun message, du moins pas
plus de 50 millisecondes.
Je pense que les commentaires sont assez prcis pour vous permettre daller plus loin.
Ceci nest naturellement pas encore une version complte mais, grce cette base,
vous devriez pouvoir facilement arriver quelque chose. Pourquoi ne pas faire un mini
tchat ?
Les dconnexions fortuites ne sont pas gres non plus. Mais vous avez assez dlments
pour faire des tests et amliorer notre serveur si cela vous tente.
349

CHAPITRE 31. LE RSEAU

Et encore plus
Je vous lai dit, le rseau est un vaste sujet et, mme en se restreignant au sujet que jai
choisi, il y aurait beaucoup dautres choses vous montrer. Je ne peux tout simplement
pas remplacer la documentation et donc, si vous voulez en apprendre plus, je vous invite
jeter un coup dil aux codes web suivants :


Module socket
B
Code web : 695428




Module select
B
Code web : 261326




Module socketserver
B
Code web : 672065


Le dernier module, socketserver, propose une alternative pour monter vos applications serveur. Il en existe dautres, dans tous les cas : vous pouvez utiliser des sockets
non bloquants (cest--dire qui ne bloquent pas le programme quand vous utilisez leur
mthode accept ou recv) ou des threads pour excuter diffrentes portions de votre
programme en parallle. Mais je vous laisse vous documenter sur ces sujets sils vous
intressent !

En rsum
Dans la structure rseau que nous avons vue, on trouve un serveur pouvant dialoguer
avec plusieurs clients.
Pour crer une connexion ct serveur ou client, on utilise le module socket et la
classe socket de ce module.
Pour se connecter un serveur, le socket client utilise la mthode connect.
Pour couter sur un port prcis, le serveur utilise dabord la mthode bind puis la
mthode listen.
Pour schanger des informations, les sockets client et serveur utilisent les mthodes
send et recv.
Pour fermer une connexion, le socket serveur ou client utilise la mthode close.
Le module select peut tre utile si lon souhaite crer un serveur pouvant grer
plusieurs connexions simultanment ; toutefois, il en existe dautres.

350

Chapitre

32

Les tests unitaires avec unittest


Difficult :
Tester ! Tout un monde. Vous allez voir dans ce chapitre comment tester le bon fonctionnement de votre programme et apprendre le rendre aussi stable que possible au fur et
mesure que vous proposerez de nouvelles amliorations.
Si vous pensez que tester ne sert rien ou que tester ne se fait que quand tout le dveloppement est fini, je vous encourage vivement lire ce chapitre, ne serait-ce que pour
information.
Pour suivre ce chapitre, vous aurez besoin de savoir comment crer des classes et avoir une
ide du fonctionnement de lhritage.

351

CHAPITRE 32. LES TESTS UNITAIRES AVEC UNITTEST

Pourquoi tester ?

On va parler de tests. . . mais quest-ce quon entend par tester ?

Cest la premire question, et elle est trs importante !


Dans ce chapitre, je vais parler de tests (principalement de tests unitaires), qui vrifient
que votre code ragit comme il le devrait et quil continue ragir comme il le devrait
aprs de nouvelles amliorations.
Certains dveloppeurs refusent de travailler sur du code qui nest pas le leur sil na
pas de documentation. Pour ce que jen ai vu, un nombre plus important encore de
dveloppeurs refuse de le faire si le code na pas de test.
Admettons que vous travaillez sur votre projet qui propose plusieurs fonctions, utilises
par dautres dveloppeurs ou utilisateurs. Vous pouvez tre tout seul sur le projet et ne
proposer quune dizaine de fonctions, cest bien suffisant, le plus important cest que
votre code est utilis par dautres.
Puis aprs avoir cod votre dixime fonction, vous commencez coder votre onzime
qui utilise une autre fonction que vous avez dj dveloppe. Mais vous vous heurtez
un problme : votre nouvelle fonction ne marche pas comme il faut.
Aprs enqute, vous vous rendez compte que ce nest pas votre fonction 11 qui pose
problme, mais la fonction (1 ou 2) que la fonction 11 appelle. Elle ne rpond plus
votre besoin et vous vous dites, naturellement, je vais la modifier .
Vous modifiez donc votre fonction 1 ou 2. Votre fonction 11 marche, enfin, sans problme. Vous proposez votre nouvelle version vos utilisateurs.
Et vous recevez un choeur de protestations : jugez donc ! Ils utilisaient votre fonction
1 ou 2 sans problme, mais avec votre nouvelle version, rien ne marche plus.
Les tests sont une solution possible : pour chaque fonctionnalit de votre programme,
il y aura un test et le test va sassurer que votre programme reste valide mme quand
vous le modifierez. Ce qui deviendra de plus en plus important au fur et mesure que
votre programme gagnera en fonctionnalits, bien entendu.
Est-ce quon doit tester un code quand tout est dvelopp ?

Non ! Si vous pouvez le faire ds le dbut, ds les premires lignes de code que vous
crivez, cest mieux. Sachez quil peut tre assez difficile dcrire des tests quand votre
programme comporte dj plusieurs centaines de fonctionnalits, il vaut mieux le faire
petit petit.
Il existe aussi plusieurs mthodes de dveloppement, dont le TDD (Test-Driven Development) qui veut que lon crive les tests avant dcrire le code. Je ne rentrerai pas
352

PREMIERS EXEMPLES DE TESTS UNITAIRES


dans le dtail ici, mais je vous conseille vivement dcrire vos tests unitaires mme
si vous navez quun tout petit projet avec 4 ou 5 fonctions. Il y a une chance non
ngligeable que le petit projet devienne grand ; avec des tests porte de main, vous
dormirez plus tranquille.
Est-ce difficile de tester un programme ?

Une fois que vous matrisez une des mthodes de test et que vous lappliquez votre
programme au fur et mesure, non ce nest absolument pas difficile. Vous allez voir
dans ce chapitre comment utiliser des tests unitaires. Il existe dautres mthodes de
test proposes par Python, mais cest celle-ci que je trouve, personnellement, la plus
rapide prendre en main ainsi que la plus flexible. Ce chapitre est l pour vous guider
par pas vers la cration de vos premiers tests unitaires et mme vers la gestion de
nombreux tests quand votre projet sera plus grand.

Qui crit les tests ?

Le dveloppeur, la plupart du temps. L encore, la mthode de test utilise peut permettre dautres personnes dcrire les tests, mais les tests unitaires sont souvent crits
par des dveloppeurs (ou des utilisateurs sachant programmer). Comme vous allez le
voir, ils ne sont pas trs difficiles crire, mais vous passerez malgr tout par Python
pour ce faire.
Passons la pratique, la dcouverte du module unittest !

Premiers exemples de tests unitaires


Le module unittest de la bibliothque standard de Python inclut le mcanisme des tests
unitaires.
Voici la structure que vous rencontrerez le plus souvent :
Pour chaque fonctionnalit, un ensemble de fonctions, de classes, de modules, de
packages et autre. Tout ce cours est l pour vous montrer comment raliser cette
partie du dveloppement ;
Pour chaque fonctionnalit, un test qui vrifie que la fonctionnalit fait bien ce quon
lui demande. Par exemple, que si une certaine fonction est appele avec certains
paramtres, elle retourne telle valeur.
Nous allons nous intresser ici ce second point dans la liste : comment tester une
fonctionnalit.
353

CHAPITRE 32. LES TESTS UNITAIRES AVEC UNITTEST

Tester une fonctionnalit existante


Pour commencer, nous allons tester une fonctionnalit dj existante, propose dans
lun des modules de Python. Je vais reprendre les exemples de la documentation officielle qui sont assez faciles comprendre.


Unit testing framework
B
Code web : 184843


Pour cet exemple, nous allons nous intresser au module random que nous avons dj
utilis. Nous allons chercher tester le fonctionnement en particulier de trois fonctions :
random.choice : cette fonction retourne un lment au hasard de la squence prcise
en paramtre.
>>> liste = ["chat", "chien", "renard", "serpent", "cheval", "parapluie"]
>>> random.choice(liste)
renard
>>>

random.shuffle : cette fonction mlange une liste. La liste dorigine est modifie.
>>>
>>>
>>>
[3,
>>>

liste = [1, 2, 3, 4, 5, 6, 7, 8, 9]
random.shuffle(liste)
liste
4, 7, 1, 8, 6, 5, 9, 2]

random.sample : cette fonction prend une squence et un nombre en paramtres. Elle


retourne une nouvelle squence contenant autant dlments que le nombre indiqu,
slectionns alatoirement dans la squence dorigine. Ce nest pas clair ?
>>> liste = [a, b, c, d, e, f, g, h, i, j]
>>> random.sample(liste, 5)
[b, a, c, j, e]
>>> # Ou peut-tre que cet exemple sera plus clair
... random.sample(range(1000), 10)
[389, 406, 890, 955, 837, 401, 971, 716, 954, 862]
>>>

Structure de base dun test unitaire


Nous le verrons plus loin, un test unitaire peut tre constitu de nombreux tests rpartis
dans plusieurs packages et modules. Pour linstant, nous nallons nous intresser qu
un test case, la forme la plus simple du test unitaire.
Pour crer un test unitaire, la premire chose est de crer une classe hritant de
unittest.TestCase :
1
2

import random
import unittest

3
4

class RandomTest ( unittest . TestCase ) :

On peut dfinir ensuite un test dans une mthode dont le nom commence par test.
354

PREMIERS EXEMPLES DE TESTS UNITAIRES


Test de la fonction random.choice
Voyons pour le premier test, le test de la fonction choice :
1

class RandomTest ( unittest . TestCase ) :

""" Test case utilis pour tester les fonctions du module '
random '. """

3
4

def test_choice ( self ) :


""" Test le fonctionnement de la fonction ' random . choice
'. """
liste = list ( range ( 10 ) )
elt = random . choice ( liste )
# V rifie que ' elt ' est dans ' liste '
self . assertIn ( elt , liste )

5
6
7
8
9
10

Quelques explications simposent pour notre mthode de test :


1. Dabord la premire ligne, on cre une liste de 0 9 ;
2. Ensuite on appelle la fonction random.choice sur notre liste et on rcupre le
retour ;
3. Enfin, on vrifie que notre lment retourn par random.choice se trouve bien
dans notre liste. On utilise pour ce faire une mthode assertIn et pas le mot
cl assert. En fait, unittest.TestCase propose plusieurs mthodes dassertion que
nous utiliserons dans nos tests unitaires. Une assertion lve une exception qui
serait considre par unittest comme une erreur. Nous verrons plus loin comment
les erreurs sont gres.
Si vous excutez ce code dans votre interprteur. . . rien ne se passe ! Vous avez cr une
classe mais vous navez pas demand au test de se lancer. Pour ce faire vous pouvez
excuter linstruction :
1

unittest . main ()

Et vous devriez obtenir quelque chose comme :


.
---------------------------------------------------------------Ran 1 test in 0.003 s
OK

Lappel unittest.main ferme la console Python, soyez prvenu, ce nest pas


une erreur mais bien un comportement attendu.
Le retour affich se dcompose en trois parties :
355

CHAPITRE 32. LES TESTS UNITAIRES AVEC UNITTEST


Dabord, la premire ligne contient un caractre par test excut. Les principaux
caractres sont un point ( . ) si le test sest valid, la lettre F si le test na pas
obtenu le bon rsultat et la lettre E si le test a rencontr une erreur (si une exception
a t leve pendant lexcution de la mthode) ;
Ensuite se trouve une ligne rcapitulative du nombre de tests excuts ; <puce>Enfin,
la dernire ligne rcapitule le nombre de russites ou checs ou erreurs. Si tout va
bien, cette dernire ligne devrait tre simplement OK .
Faisons chouer un test
Modifions notre test pour tre sr de provoquer un chec :
class RandomTest ( unittest . TestCase ) :

1
2

""" Test case utilis pour tester les fonctions du module '
random '. """

3
4

def test_choice ( self ) :


""" Test le fonctionnement de la fonction ' random . choice
'. """
liste = list ( range ( 10 ) )
elt = random . choice ( liste )
self . assertIn ( elt , ( 'a ' , 'b ' , 'c ') )

5
6
7
8
9

Et aprs un appel unittest.main() :


F
==============================================================
FAIL : test_choice ( __main__ . RandomTest )
Test le fonctionnement de la fonction random . choice .
-------------------------------------------------------------Traceback ( most recent call last ) :
File " code . py " , line 13 , in test_choice
self . assertIn ( elt , ( a , b , c ) )
AssertionError : 0 not found in ( a , b , c )
-------------------------------------------------------------Ran 1 test in 0.004 s
FAILED ( failures =1)

Vous voyez que lon obtient pas mal dinformations sur les tests qui ne marchent pas.
Dabord, notez quici, on parle dchec (failure) et non pas derreur (error). Cela signifie
que notre assertion ne sest pas vrifie (regardez le traceback) mais que notre test sest
correctement excut. Vous pouvez essayer de provoquer une erreur dans la mthode
de test aussi, pour voir le rsultat.
Le traceback est assez dtaill : il donne la ligne de lerreur avec les appels successifs,
si on a besoin de remonter la piste de lerreur. Le message derreur lui-mme donne des
informations plus prcises sur pourquoi le test a chou (0 not found in (a, b, c)).
356

PREMIERS EXEMPLES DE TESTS UNITAIRES


Test de la fonction random.shuffle
Intressons-nous maintenant la fonction random.shuffle. Souvenez-vous, elle prend
une liste en paramtre et mlange cette liste alatoirement.
En vous inspirant du premier exemple, essayez dcrire la mthode de test correspondante. Il vous faut rflchir comment vrifier quune liste, aprs avoir t mlange,
correspond une liste dlments de 0 </italique>9</italique>.
Je vous conseille dutiliser cette fois la mthode dassertion assertEqual qui prend
deux arguments en paramtre et vrifie le test si les arguments sont identiques. Vous
trouverez une liste des mthodes dassertion les plus communes plus bas.
vous de jouer !
1

class RandomTest ( unittest . TestCase ) :

2
3

""" Test case utilis pour tester les fonctions du module '
random '. """

4
5
6
7
8
9
10
11

# Autres m thodes de test


def test_shuffle ( self ) :
""" Test le fonctionnement de la fonction ' random .
shuffle '. """
liste = list ( range ( 10 ) )
random . shuffle ( liste )
liste . sort ()
self . assertEqual ( liste , list ( range ( 10 ) ) )

Comme vous le voyez, on appelle la fonction random.shuffle avant de trier de nouveau


notre liste. Une fois la liste trie de nouveau, elle devra tre identique notre liste
dorigine (list(range(10))).
Ici, nous avons utilis la mthode assertEqual qui sera sans doute celle que vous utiliserez le plus souvent. Nous verrons un peu plus loin une liste des mthodes dassertion
proposes par unittest.TestCase.
Test de la fonction random.sample
Enfin, crivons notre mthode de test de la fonction random.sample. Souvenez-vous,
cette fonction prend deux paramtres : une squence et un nombre K. Elle retourne
une liste contenant K lments slectionns alatoirement dans notre squence de base.
Voyons une premire approche :
1

class RandomTest ( unittest . TestCase ) :

2
3

""" Test case utilis pour tester les fonctions du module '
random '. """

4
5
6

# Autres m thodes de test


def test_sample ( self ) :

357

CHAPITRE 32. LES TESTS UNITAIRES AVEC UNITTEST


7
8
9
10
11

""" Test le fonctionnement de la fonction ' random . sample


'. """
liste = list ( range ( 10 ) )
extrait = random . sample ( liste , 5 )
for element in extrait :
self . assertIn ( element , liste )

Jusquici ce nest pas bien diffrent de ce que nous avons fait un peu plus haut.
Avez-vous essay random.sample en prcisant un nombre K plus lev que la taille de
la squence ?
1
2
3
4
5
6
7
8

>>> liste = list ( range ( 10 ) )


>>> random . sample ( liste , 20 )
Traceback ( most recent ca