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 !
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
Avant-propos
ii
iii
iii
iii
iii
Remerciements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
iv
Introduction Python
La communication humaine . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
Installer Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Sous Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Sous Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Sous Mac OS X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
14
15
Saisir un nombre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
Oprations courantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
19
20
. . . . . . . . . . . . . . . . . . . . . . . . . .
20
20
22
22
23
Un petit bonus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
25
26
26
La fonction type . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
27
La fonction print . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
28
vi
31
32
Forme minimale en if . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
33
De nouveaux oprateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
36
Prdicats et boolens . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
37
38
Avant de commencer . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
Sujet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
Solution ou rsolution . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
Correction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
41
45
46
La boucle while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
47
La boucle for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
49
51
Le mot-cl break . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
51
Le mot-cl continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
51
53
54
La cration de fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . .
54
56
57
Linstruction return . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
58
59
Syntaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
59
Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
60
. . . . . . . . . . . . . . . . . . . . . . . . . . .
60
60
La mthode import . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
60
62
63
Bilan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
64
67
68
Fini, linterprteur ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
68
68
Quelques ajustements . . . . . . . . . . . . . . . . . . . . . . . . . . . .
70
71
71
73
Les packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
74
En thorie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
74
En pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
75
vii
80
81
82
82
84
85
Les assertions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
85
86
9 TP : tous au ZCasino
II
79
89
Notre sujet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
90
90
90
Le module random . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
91
Arrondir un nombre . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
91
vous de jouer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
91
Correction ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
92
Et maintenant ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
94
95
97
98
98
109
121
133
145
. . . . . . . . . 146
. . . . . . . . . . . . . . . . . . . . . . . . . 147
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
. . . . . . . . . . . . . . . . . . . . 152
155
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
163
III
171
173
189
195
213
227
239
249
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
257
273
IV
285
287
297
307
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
323
331
337
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
xv
351
365
375
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
Annexes
385
387
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
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
413
. . . . . . . . . . . . . . . . . . . . . . . . . . . 417
xviii
Premire partie
Introduction Python
Chapitre
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.
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.
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.
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
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. . .
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
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
12
Chapitre
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
14
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.
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
>>>
>>> 9.5
15
9.5
>>>
Oprations courantes
Bon, il est temps dapprendre utiliser les principaux oprateurs de Python, qui vont
vous servir pour la grande majorit de vos programmes.
>>> 3 + 4
7
>>> -2 + 93
91
>>> 9.5 + 2
11.5
>>> 3.11 + 2.08
5. 18 99 999 999999995
>>>
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
>>> 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
>>>
>>> 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
18
Chapitre
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
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
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
21
>>> 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.
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
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
On doit galement chapper les guillemets si on utilise les guillemets comme dlimiteurs.
1
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
1
2
3
4
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.
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
>>>
26
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
>>> a = 3
>>> type ( a )
Vous obtenez :
1
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
27
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 )
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
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
30
Chapitre
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
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 )
33
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 .")
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.")
34
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
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
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
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
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 !
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
37
else :
print (" a n est pas dans l intervalle .")
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
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).
quoi on joue ?
38
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
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
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
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
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
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
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
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
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
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
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
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
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
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
47
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
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
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
. . . 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
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
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
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
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
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
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 ?
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 .
55
4
5
6
7
8
9
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
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.
def exemple () :
57
print ( " Un exemple d ' une fonction sans param tre " )
3
4
exemple ()
5
6
7
8
9
exemple ()
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
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
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
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 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
>>>
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
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
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
19
20
acosh ( ... )
61
21
22
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
3
4
5
sqrt ( ... )
sqrt ( x )
7
8
9
>>>
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
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
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
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
66
Chapitre
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
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
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
# ! 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
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
6
7
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
16
17
18
70
2
3
4
5
6
7
8
9
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
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
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.
2
3
4
5
6
7
8
9
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
2
3
import os
4
5
6
7
8
9
10
11
12
13
14
15
16
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
Si vous ne voulez importer quun seul module (ou quune seule fonction) dun package,
vous utiliserez une syntaxe similaire, assez intuitive :
1
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
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
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
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
try :
# Bloc essayer
except :
# Bloc qui sera ex cut en cas d ' erreur
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
try :
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 :
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
try :
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
try :
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 :
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
>>> 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 :
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
>>> var = 5
>>> assert var == 5
>>> assert var == 8
Traceback ( most recent call last ) :
File " < stdin >" , line 1 , in < module >
85
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.
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
86
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
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
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.
90
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
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.
2
3
4
5
import os
from random import randrange
from math import ceil
6
7
8
9
10
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
31
32
33
34
35
92
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
93
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
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
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.
Sachez que, dans les anciennes versions de Python, il y avait un module spcialis dans
98
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
4
5
6
7
100
INTRODUCTION
>>>
101
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
>>>
>>>
>>>
>>>
1
2
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
>>>
>>>
>>>
>>>
...
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
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
. . . affichera :
1
2
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
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 ."
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.
>>>
>>>
S
>>>
l
>>>
!
>>>
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
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
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
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
107
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
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 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
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
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
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
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.
>>>
>>>
>>>
[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
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 )
[ a , b , c , d , e ]
>>> 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.
>>> variable = 34
>>> variable
113
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
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
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 !
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
>>> 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 ,
>>>
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
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
>>> (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.
4
5
6
7
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
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
120
Chapitre
12
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
122
3
4
5
6
7
8
9
123
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.
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
124
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
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
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
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#
#
#
#
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
1
2
3
4
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 !
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.
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.
>>> 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
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
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
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
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
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
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
>>> mon_dictionnaire = {}
>>> mon_dictionnaire [" pseudo "] = " Prolixe "
>>> mon_dictionnaire [" mot de passe "] = "*"
>>> mon_dictionnaire [" pseudo "] = "6 pri1 "
>>> mon_dictionnaire
{ mot de passe : * , pseudo : 6 pri1 }
>>>
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 }
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
placard = { " chemise " :3 , " pantalon " :6 , " tee - shirt " : 7 }
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.
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
>>>
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
>>> fruits = {" pommes ":21 , " melons ":3 , " poires ":31}
>>> for cle in fruits :
...
print ( cle )
...
melons
poires
pommes
>>>
>>> fruits = {" pommes ":21 , " melons ":3 , " poires ":31}
139
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.
>>> 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
140
>>> fruits = {" pommes ":21 , " melons ":3 , " poires ":31}
>>> for cle , valeur in fruits . items () :
...
print (" La cl {} contient la valeur {}.". format ( cle ,
valeur ) )
...
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.
Pour capturer tous les paramtres nomms non prciss dans un dictionnaire, il faut
mettre deux toiles ** avant le nom du paramtre.
141
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.
>>> 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
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
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
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.
>>> 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:\.
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
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.
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
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
149
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.
>>> 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
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
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
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
>>> 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.
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
1
2
3
4
5
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
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
>>> 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.
>>>
4
5
6
7
8
9
10
11
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
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
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
>>> 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 ?
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
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
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.
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
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
165
fonctions.py
1
2
3
4
5
6
7
import os
import pickle
from random import choice
8
9
10
11
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
19
20
21
22
23
24
25
26
27
28
29
30
31
166
CORRECTION PROPOSE
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
73
167
75
76
77
78
def choisir_mot () :
""" Cette fonction renvoie le mot choisi dans la liste des
mots
liste_mots .
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
pendu.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
168
CORRECTION PROPOSE
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
169
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
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
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
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.
175
1
2
3
4
5
6
7
8
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
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
177
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
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
6
7
8
9
>>>
0
>>>
>>>
1
>>>
>>>
Compteur . objets_crees
a = Compteur () # On cr e un premier objet
Compteur . objets_crees
b = Compteur ()
Compteur . objets_crees
179
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.
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
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
14
15
16
17
18
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
181
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
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 ?
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
7
8
9
1
2
3
4
5
6
7
8
9
10
11
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
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.
Vous le pouvez. Sachez quen modifiant la valeur de lattribut, vous modifiez aussi
lattribut dans lobjet.
1
2
3
4
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
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
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
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.
la
la
la
la
mthode
mthode
mthode
mthode
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
18
19
20
21
22
23
24
25
26
27
28
29
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
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
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
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
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
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
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
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
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
198
4
5
6
7
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
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
4
5
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
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
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
14
15
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.
class Duree :
""" Classe contenant des dur es sous la forme d ' un nombre de
minutes
203
3
4
5
6
7
8
9
10
11
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
204
# 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
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
Et en images :
1
2
206
>>> d1 = Duree (8 , 5)
>>> d1 += 128
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.
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
208
class Temp :
""" Classe contenant plusieurs attributs , dont un temporaire
"""
9
10
11
12
13
14
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
...
2
3
4
5
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.
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
212
Chapitre
20
213
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 ']
>>>
>>> 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
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 !
etudiants = [
( " Cl ment " , 14 , 16 ) ,
( " Charles " , 12 , 15 ) ,
( " Oriane " , 14 , 18 ) ,
( " Thomas " , 11 , 12 ) ,
( " Damien " , 12 , 15 ) ,
]
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 ?
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
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.
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
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.
class Etudiant :
2
3
4
5
6
7
8
9
10
11
12
13
"""
14
15
16
17
218
19
20
21
22
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
219
]
>>>
< tudiant
< tudiant
< tudiant
< tudiant
< tudiant
On obtient la mme chose que dans notre exercice prcdent, quand nous utilisions des
tuples. Je trouve personnellement cette mthode plus lisible.
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
Pour faire la mme chose sans fonction lambda, avec la fonction itemgetter du module
operator :
1
2
class Etudiant :
221
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
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
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.
222
>>> sorted ( etudiants , key = attrgetter ( " age " , " moyenne " ) )
3
4
5
6
7
8
9
]
>>>
< tudiant
< tudiant
< tudiant
< tudiant
< tudiant
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
4
5
6
7
8
9
10
"""
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
223
2
3
4
5
6
< Ligne
< Ligne
< Ligne
< Ligne
d ' inventaire
d ' inventaire
d ' inventaire
d ' inventaire
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
2
3
4
5
6
< Ligne
< Ligne
< Ligne
< Ligne
d ' inventaire
d ' inventaire
d ' inventaire
d ' inventaire
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
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
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
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
229
12
13
14
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
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
14
15
16
17
18
19
20
21
22
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
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
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
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
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
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.
2
3
4
234
|
|
|
|
|
|
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.
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
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
238
Chapitre
22
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
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 :
240
LES ITRATEURS
17
>>>
6
7
8
9
10
11
12
13
241
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
21
22
23
24
25
26
27
28
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
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.
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
243
...
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
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
3
4
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 ?
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
6
7
8
9
10
11
12
13
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.
247
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
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
251
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
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
253
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
254
CORRECTION PROPOSE
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
255
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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.
257
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.
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 (...)
4
5
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.
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.
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
4
5
6
7
8
9
10
11
12
13
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 >
>>>
@mon_decorateur
def salut () :
...
def 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
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.
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
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
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
import time
7
8
9
10
11
12
13
14
15
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
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
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
3
4
265
...
2
3
4
5
6
7
8
9
10
11
12
13
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
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.
@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
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.
6
7
8
9
10
269
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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
EXEMPLES DAPPLICATIONS
12
>>>
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
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
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
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
4
5
6
7
8
9
10
11
12
13
14
275
15
16
format ( cls ) )
# On laisse le travail object
return object . __new__ ( cls , nom , prenom )
17
18
19
20
21
22
23
24
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.
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
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
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.
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
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
278
25
26
27
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.
La mthode __new__
Elle prend quatre paramtres :
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
3
4
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
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
2
3
4
5
6
7
8
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
2
3
4
5
281
7
8
9
10
11
12
13
14
1
2
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 >}
>>>
2
3
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
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
284
Quatrime partie
285
Chapitre
26
287
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
Explication
0, 1 ou plus
1 ou plus
0 ou 1
Expression
abc*
abc+
abc ?
Vous pouvez galement contrler prcisment le nombre doccurences grce aux accolades :
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.
>>> import re
>>>
>>> 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
291
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
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 } $
LE MODULE RE
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 ) :
")
( 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
(? P < id >[ 0 - 9 ] { 2 } )
294
LE MODULE RE
10
11
12
^[ A - Za - z0 - 9 ] {6 , } $
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
En rsum
Les expressions rgulires permettent de chercher et remplacer certaines expressions
dans des chanes de caractres.
295
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
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
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
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
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.
time . localtime ()
299
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.
LE MODULE TIME
1
2
3
4
5
6
7
8
9
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
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
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
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 !
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
Et bien entendu, vous pouvez manipuler ces dates simplement et les comparer grce
aux oprateurs usuels, je vous laisse essayer !
303
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
306
Chapitre
28
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
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.
308
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
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 ?
309
import os
os . getcwd ()
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 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
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
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
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
8
9
10
11
12
13
14
15
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
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
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
313
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.
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
314
import sys
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ 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
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 ()
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
optional arguments :
-h , -- help show this help message and exit
>
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
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
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
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
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
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.
321
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.
323
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
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
324
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
1
2
3
4
5
6
7
8
9
10
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
Alors que :
1
2
3
326
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
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
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).
328
>>> 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
330
Chapitre
30
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
1
2
3
4
5
6
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
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
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 !
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.
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
>>> b test
b test
>>>
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
import hashlib
from getpass import getpass
3
4
5
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
18
19
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
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
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.
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
341
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
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.
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
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
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
344
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
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
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
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
6
7
8
9
10
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
25
26
348
# 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
53
54
co n n e x i o n _p r i ncipale . close ()
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
351
Pourquoi tester ?
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
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.
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 !
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]
import random
import unittest
3
4
On peut dfinir ensuite un test dans une mthode dont le nom commence par test.
354
""" Test case utilis pour tester les fonctions du module '
random '. """
3
4
5
6
7
8
9
10
unittest . main ()
1
2
""" Test case utilis pour tester les fonctions du module '
random '. """
3
4
5
6
7
8
9
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
2
3
""" Test case utilis pour tester les fonctions du module '
random '. """
4
5
6
7
8
9
10
11
2
3
""" Test case utilis pour tester les fonctions du module '
random '. """
4
5
6
357
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