0% ont trouvé ce document utile (0 vote)
58 vues194 pages

Python

Transféré par

ntuta
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats DOCX, PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
58 vues194 pages

Python

Transféré par

ntuta
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats DOCX, PDF, TXT ou lisez en ligne sur Scribd
Vous êtes sur la page 1/ 194

1

PYTHON

TABLE DES MATIERES


INTRODUCTION AU COURS PYTHON

Introduction à Python

L’environnement de travail Python

Syntaxe de base et exécution d’instructions Python

Chapitre 1. LES VARIABLES ET LES TYPES DE VALEURS PYTHON

Les variables Python

Les types de données ou types de valeurs Python

Les opérateurs Python

Les listes Python

Les tuples Python

Les dictionnaires Python

Les ensembles ou sets Python

Chapitre 2. LES STRUCTURES DE CONTRÔLE PYTHON

Les structures conditionnelles if, if…else et if…elif…else en Python

Créer des conditions Python complexes

Les boucles Python for et while

Chapitre 3. LES FONCTIONS PYTHON

Introduction aux fonctions Python

Notions avancées sur les paramètres des fonctions Python

Contrôle des valeurs de retour d’une fonction Python

La portée des variables en Python

Annexe 1 : Quelques fonctions Python utiles

Chapitre 4. PYTHON ORIENTÉ OBJET


2
PYTHON

Introduction à l’orienté objet en Python

Classes, objets et attributs en Python orienté objet

Héritage et polymorphisme en Python orienté objet

Gérer la visibilité des membres de classe en Python orienté objet

Itérateurs et générateurs en Python orienté objet

Annexe 2 : Quelques méthodes Python utiles

Chapitre 5. MODULES STANDARDS ET PAQUETS PYTHON

Les modules et paquets Python

Modules Python standards Math, Random et Statistics

Les modules Python standards Datetime, Time et Calendar

Le module Python standard Re – expressions régulières ou rationnelles

Chapitre 6. MANIPULATION DE FICHIERS AVEC PYTHON

Introduction à la manipulation de fichiers en Python

Opérations sur les fichiers en Python

L’échange de données en Python avec le module Json

Chapitre 7. GESTION DES ERREURS PYTHON

Introduction à la gestion d’erreurs ou d’exceptions en Python

Gérer les exceptions en Python avec try, except, else et finally

CONCLUSION DU COURS PYTHON

Conclusion du cours Python

https://www.pierre-giraud.com/python-apprendre-programmer-cours/
3
PYTHON

Objectifs du cours Python


Bienvenue dans ce cours traitant d’un des langages de programmation les plus
célèbres et les plus plébiscités : Python. Le but de ce cours est de comprendre ce
qu’est Python, ce que Python permet de réaliser et d’explorer ses différentes
fonctionnalités et de vous apprendre à les utiliser pas à pas.

L’idée de ce cors n’est pas simplement de vous présenter les différents éléments
de Python un-à-un mais véritablement de vous expliquer quand et comment
utiliser chaque nouvelle notion afin que vous ayez le plus rapidement une vue
d’ensemble claire pour utiliser les différents éléments de ce langage au bon
moment et à bon escient.

Mon but, à travers ce cours, est de vous amener vers une certaine autonomie et
de faire en sorte que vous soyez capables de réaliser de petits projets Python par
vous même à la fin de celui-ci.

Prérequis pour suivre ce cours Python


Python est un langage qui a été créé pour être le plus lisible et le plus simple à
comprendre et à utiliser possible. C’est donc un bon choix pour des débutants et
ce n’est d’ailleurs pas par hasard qu’il est l’un des langages les plus
recommandés aux personnes souhaitant s’initier à la programmation.

En effet, la syntaxe de Python encourage la mise en place de nombreuses bonnes


pratiques qui vous seront utiles par la suite dans votre vie de développeur.

Ce cours est ainsi ouvert à tous : nous commencerons par nous familiariser avec
l’environnement de travail Python avant de présenter des structures simples puis
irons progressivement vers des notions plus complexes.

Méthodologie du cours Python


Dans un but pédagogique, et afin de vous fournir la meilleure expérience
d’apprentissage possible, ce cours a été divisé en de multiples sous-chapitres eux
mêmes regroupés en sections.
4
PYTHON

Vous pouvez à tout moment voir le sommaire du cours sur votre gauche pour
vous repérer et naviguer entre les différentes leçons du cours.

Chaque nouvelle section dispose d’un script illustré par de nombreux exemples.
Dans ce cours Python, nous travaillerons avec l’interpréteur Python en mode
interactif, ce qui signifie que nous taperons les différentes commandes Python
directement dans l’invite de commande ou le terminal. Je vous invite fortement
à faire l’effort de recopier chacun de mes codes vous même car c’est en
pratiquant qu’on apprend le mieux et car c’est comme cela que vous pourrez
vous familiariser le plus vite avec la syntaxe Python et cela rendra le cours
beaucoup plus dynamique pour vous.

A l’inverse, je vous déconseille de « rusher » ce cours et d’essayer d’en faire le


tour en deux jours : cela ne sera pas efficace car vous ne pourrez pas apprendre à
programmer comme cela. Il faut du temps pour intégrer les différentes structures
de langage et la place et l’utilité de chacune d’entre elles.

Contenu du cours Python


Dans ce cours, nous allons nous appliquer à décomposer et à expliquer chaque
notion communément utilisée de Python. Nous allons commencer avec
l’installation de (l’interpréteur) Python et avec quelques commandes simples
pour se familiariser avec l’environnement Python.

Ensuite, nous découvrirons les variables Python, puis les types de données, les
structures de contrôles (conditions et boucles) et les fonctions Python.

Dans un troisième temps, nous nous attaquerons à ce qui fait selon moi le coeur
de Pyhon : l’orienté objet les classes, les instances et les objets.

Nous terminerons finalement avec d’autres opérations et notions qu’il faut


connaitre en Python comme la manipulation des fichiers, l’utilisation des
modules et la gestion des erreurs.
5
PYTHON

INTRODUCTION A PYTHON
Python est un langage de programmation créé par Guido Van Rossum. La
première version publique du langage est sortie en 1991. Son nom provient de la
troupe de comiques anglais les Monty Python.

Python est un langage interprété, qui se veut simple à comprendre, modulable et


aux applications multiples. C’est aujourd’hui un des langages les plus utilisés et
les plus plébiscités par les développeurs.

Cette première leçon a pour but de présenter le langage Python et de poser


quelques concepts fondamentaux relatifs aux langages de programmation qui
nous seront utiles par la suite.

Python, un langage de programmation

Un ordinateur est une machine dont la fonction principale est de traiter des
données, c’est-à-dire d’exécuter des séries d’instructions pour effectuer
différentes tâches.

En tant que développeurs, nous allons vouloir fournir nos séries d’instructions
aux ordinateurs afin qu’ils exécutent certaines tâches précises dans un certain
ordre.

Pour cela, il va falloir que l’ordinateur nous comprenne et il va donc falloir


qu’on exprime nos instructions dans un langage qu’il comprend. Le souci, ici,
est que les ordinateurs ne comprennent qu’un seul langage : le binaire ou
“langage machine” qui est très opaque pour nous (les Humains) et très long à
écrire.
6
PYTHON

Pour pallier à ce problème, certaines personnes ont créé ce qu’on appelle des
langages de programmation. Le but premier de tout langage de programmation
est de passer des instructions à l’ordinateur.

Schématiquement, on utilise des langages de programmation car il est plus facile


de nous exprimer et d’expliciter nos séries d’instruction en suivant leurs
conventions d’écriture plutôt que de passer nos instructions directement en
binaire à l’ordinateur.

Le langage de programmation se charge de la conversion : il reçoit nos


instructions et les transforme en binaire pour les passer à l’ordinateur afin que
celui-ci les exécute.

Tous les langages de programmation ne sont pourtant pas égaux : certains sont
plus facilement compréhensibles pour nous que d’autres et certains nous
permettent de transmettre uniquement certaines instructions à l’ordinateur.

Python est un langage de programmation dit de “très haut niveau”. Cela signifie
qu’il possède un haut niveau d’abstraction par rapport au langage machine. Pour
le dire très simplement : plus un langage de programmation est de “haut niveau”,
plus sa syntaxe se rapproche de notre langage (l’anglais) plutôt que du langage
machine. Un langage de haut niveau est donc plus facile à comprendre et à
utiliser qu’un langage de plus bas niveau.

Python, un langage interprété

Comment font les langages de programmation pour transformer nos instructions


en instructions compréhensibles par un ordinateur ? Ils leur faut un traducteur.
Certains langages utilisent un interpréteur comme traducteur tandis que d’autres
utilisent un compilateur.

Un interpréteur se distingue d’un compilateur par le fait que, pour exécuter un


programme, les opérations d’analyse et de traductions sont réalisées à chaque
exécution du programme (par un interprète) plutôt qu’une fois pour toutes (par
un compilateur).

L’interprétation repose sur l’exécution dynamique du programme par un autre


programme (l’interpréteur), plutôt que sur sa conversion en un autre langage
(par exemple le langage machine).

Ainsi, contrairement au compilateur, l’interpréteur exécute les instructions du


programme (ou en évalue les expressions), au fur et à mesure de leur lecture
pour interprétation. Du fait de cette phase sans traduction préalable, l’exécution
7
PYTHON

d’un programme interprété est généralement plus lente que le même programme
compilé.

En revanche, les langages interprétés sont généralement plus simples à


appréhender puisqu’on ne passe pas par une étape de compilation avant
d’exécuter son programme et la portabilité.

En effet, un langage comme Python fonctionnera avec n’importe quel système


d’opération (OS) du moment que l’OS en question possède l’interpréteur
Python. Un compilateur, de l’autre côté, va produire un programme écrit en
langage assembleur et ce langage assembleur va être différent pour chaque OS.
Par conséquent, les programmes compilés ne peuvent s’exécuter que sur des
ordinateurs dotés de la même architecture que l’ordinateur sur lequel ils ont été
compilés.

Python, un langage extensible et polyvalent

Python est modulable et extensible : une fois qu’on connait les bases du langage,
on va pouvoir relativement simplement ajouter de nouvelles fonctions ou
modules pour étendre les possibilités de ce langage.

Python est un langage de programmation conçu dès le départ pour être “full
stack”, c’est-à-dire pour avoir de multiples applications à la différence du PHP
par exemple qui a clairement été imaginé pour fonctionner dans un contexte
Web.

Ce langage est un langage orienté objet à la base mais Python supporte


également d’autres paradigmes comme la programmation procédurale et
fonctionnelle. Un paradigme est une “façon de coder” ou une “façon d’imaginer
le code et de le structurer”. Nous reviendrons là dessus plus tard.

Un point sur les versions Python

Avant de passer à la suite, j’aimerais vous parler des différentes versions du


langage Python car, sur ce point, l’équipe de développement de Python a fait des
choix particuliers.

En informatique, les langages évoluent par “version”. Les équipes qui créent un
langage travaillent sans cesse à l’amélioration de celui-ci mais chaque
changement fait sur le langage n’est pas immédiatement intégré au langage ni
disponible au public.

Au contraire, une liste de modifications / ajouts sont faits au langage en arrière


plan et, dès que l’équipe gérant l’évolution du langage juge les changements
8
PYTHON

suffisamment importants et stables, une nouvelle “version” du langage qui


incorpore ces changement est distribuée.

La première grosse mise à jour de Python date de 2000 avec la version Python 2.
Les versions se sont ensuite enchainées normalement avec Python 2.1, 2.2, 2.3,
etc. jusqu’en 2009 avec la sortie de Python 3.

Pour Python 3, l’équipe qui gère l’évolution du Python a fait le choix audacieux
de partir sur de nouvelles bases et de casser la compatibilité avec les anciennes
versions.

Généralement, lorsqu’un langage évolue et que de nouvelles versions paraissent,


les équipes de développement font bien attention à proposer une compatibilité
ascendante, c’est-à-dire à faire en sorte que les codes créés sous d’anciennes
versions fonctionnent toujours avec les nouvelles versions des langages. En
effet, sans ce principe de compatibilité, la plupart des programmes et des sites
Web ne fonctionneraient pas puisque les développeurs de ceux-ci devraient
absolument les modifier à chaque nouvelle version d’un langage utilisé pour
coller aux nouvelles normes.

A l’inverse, le fait de proposer une comptabilité ascendante entre chaque version


pose de vrais problèmes d’héritage aux développeurs d’un langage puisque ces
derniers sont obligés de conserver certaines syntaxes et fonctionnalités
totalement obsolètes.

Voulant modifier en profondeur leur langage et proposer une version beaucoup


plus “propre” et au goût du jour, la Python Software Foundation (l’équipe
chargée du développement du Python) a donc décidé de faire table rase pour
Python 3 et de partir sur de nouvelles bases.

Le souci ici est que Python 2.x était déjà très populaire à l’époque et que cela
allait mettre de nombreuses personnes dans l’embarras. L’équipe de Python a
donc fait le choix de conserver deux versions du langage : Python 2.x et Python
3.x et de les faire évoluer de front. Pour être tout à fait précis, la version 3 est la
version dont les fonctionnalités allaient continuer d’évoluer tandis que la version
2 n’allait recevoir que des mises à jour liées à la sécurité.

Aujourd’hui encore, on retrouve ces deux versions de Python qui co-existent.


Pour nous, cependant, le problème ne se pose pas : nous travaillerons bien
évidemment avec la dernière version en date de Python qui est à l’heure où
j’écris la version 3.7.3.
9
PYTHON

L’environnement de travail Python


Dans cette leçon, nous mettons en place notre environnement de travail en nous
équipant des logiciels nécessaires pour pouvoir développer en Python.

Coder en Python : simple et gratuit

Python est un langage Open Source. Cela signifie que ses sources et son
interpréteur sont disponibles au public et donc que n’importe qui peut
commencer à développer ses propres programmes Python gratuitement.

Pour coder en Python, un seul programme va être strictement obligatoire :


l’interpréteur Python qui va pouvoir être utilisé de manière dynamique et nous
afficher les résultats de nos codes immédiatement.

En pratique, cependant, nous voudrons souvent enregistrer nos différents scripts


dans des fichiers plutôt que d’écrire des séries d’instructions à exécuter
immédiatement. Pour cela, nous avoir besoin d’un éditeur de texte ou d’un IDE
(Environnement de Travail Intégré).

L’interpréteur Python

Python est un langage interprété, ce qui signifie qu’on va avoir besoin d’un
programme nommé interpréteur pour convertir nos instructions Python en un
langage compréhensible par notre ordinateur.

L’interpréteur Python est disponible en téléchargement gratuit sur le site officiel


du langage, dans la rubrique téléchargement :
https://www.python.org/downloads/.

Sur cette page, commencez par télécharger la dernière version stable de Python
qui correspond à votre système. L’interpréteur sera parmi les fichiers
téléchargés.

Notez que si vous utilisez un Mac un interpréteur Python devrait déjà être
installé sur votre machine par défaut. Cependant, l’interpréteur pré-installé
risque de correspondre à une ancienne version et nous voulons dans ce cours
travailler avec la dernière version stable du langage (Python 3.7.3 à l’heure de ce
tutoriel).

Une fois que vous avez téléchargé la ressource Python disponible sur le site
officiel, ouvrez la en double cliquant dessus. Un processus d’installation
démarre. Si vous êtes sur Windows, cochez la case “Ajouter Python 3.x au
PATH”. Suivez ensuite le processus d’installation comme pour n’importe quel
autre logiciel.
10
PYTHON

Vous venez d’installer l’interpréteur Python ainsi que d’autres ressources pour
vous aider dans vos développements Python, notamment IDLE et Python
Launcher si vous utilisez un Mac.

IDLE est un environnement de développement intégré spécialement pour Python


qui nous permet d’exécuter directement du code Python. Python Launcher
permet lui d’exécuter du code Python créé dans des fichiers séparés .py en
double cliquant simplement sur ces fichiers. Ces deux logiciels sont
extrêmement puissants et pratiques, même si nous ne nous en servirons pas dans
ce cours pour faciliter la compréhension et le suivi de tous.

Pour exécuter nos scripts Python, il va falloir les passer à l’interpréteur. Pour
cela, nous allons utiliser l’invite de commande (Windows) ou le terminal (Mac).

L’invite de commande se trouve dans le menu Démarrer de Windows sous le


nom cmd. Le terminal se trouve dans le dossier Applications, puis Utilitaire de
Mac. Dès que vous trouvez l’invite de commande ou le terminal, ouvrez le. Une
fenêtre noire devrait apparaitre.

Une fois que vous êtes dans l’invite de commande ou dans le terminal,
commencez par vérifier que l’interpréteur Python a bien été installé. Pour cela,
tapez la commande python -V (avec un V majuscule) et pressez la touche
Entrée. Si vous êtes sur Mac, Python 2.7 devrait déjà être installé et sera
probablement la version renvoyée. Tapez plutôt la commande python3 -V. La
version de l’interpréteur Python installée devrait vous être renvoyée.

Pour appeler l’interpréteur, tapez simplement python3 (ou python3.7 dans le cas
où il y aurait une ambiguïté) (Mac) ou python (Windows). Si la version de
l’interpréteur vous est renvoyée te que vous voyez un triple chevron $gt;$gt;$gt;,
c’est gagné ! Ce triple chevron est le moyen pour l’interpréteur de nous dire “je
suis prêt à recevoir la prochaine instruction”.
11
PYTHON

A partir de là, nous avons deux options : on va pouvoir soit directement écrire
nos instructions Python dans l’invite de commande ou dans le terminal pour les
exécuter immédiatement, soit créer des fichiers de script Python avec
l’extension .py avec un éditeur de texte et les passer ensuite à l’interpréteur.
Dans l’image ci-dessus, par exemple, j’ai tapé et exécuté une première
instruction Python print() qui sert simplement à afficher un message.

Ecrire son code directement dans l’invite de commande / le terminal est très
pratique pour tester rapidement un code. Cependant, en conditions “réelles”,
c’est-à-dire lorsque vous devrez créer de vrais programmes contenant
potentiellement plusieurs scripts ou lorsque vous voudrez distribuer votre code,
vous stockerez vos instructions dans des fichiers .py que vous allez créer avec
un éditeur de texte ou un IDE.

L’éditeur de texte

Si vous avez décidé de suivre ce tutoriel sur Python, je suppose que vous savez
déjà ce qu’est un éditeur de texte.

Un éditeur de texte nous permet tout simplement d’écrire des lignes de code et
d’enregistrer nos fichiers au bon format.

Il existe des centaines d’éditeur prêt à télécharger sur le Web et la majorité


d’entre eux sont gratuits. Je n’ai pas de conseil spécifique à vous donner quant
au choix de votre éditeur de texte : essayez simplement d’en trouver un avec
lequel vous êtes à l’aise et si possible installez plutôt un IDE (Environnement de
Travail Intégré) qu’un simple éditeur.
12
PYTHON

Les IDE disposent de fonctionnalités supplémentaires comme des mécanismes


d’auto-complétion du code ou encore de systèmes de détection des erreurs de
syntaxe dans un code et de proposition de modification.

Pour ma part, dans ce cours, j’utiliserai l’IDE Visual Studio Code de Microsoft
mais vous pouvez utiliser Brackets, Atom, Sublime Text ou encore Komodo si
vous préférez.

Notez par ailleurs qu’il existe certains éditeurs spécialement conçus pour écrire
du code Python dont le célèbre PyCharm notamment.

Syntaxe de base et exécution d’instructions Python


Dans cette leçon, nous allons découvrir quelques éléments de syntaxe de base de
Python. Nous allons également exécuter nos première instructions Python en
utilisant l’interpréteur de manière interactive ou en créant un fichier Python
qu’on va ensuite passer à l’interpréteur.

Créer un fichier Python

Nous avons deux choix pour exécuter du code Python : on peut soit écrire
directement notre code dans l’invite de commande (Windows) ou dans le
terminal (Mac) afin que l’interpréteur Python interprète directement notre code
et nous renvoie son résultat ou on peut créer des fichiers Python avec un
ensemble d’instructions à l’intérieur et qu’on va ensuite passer à l’interpréteur.

L’intérêt principal d’un fichier est qu’il peut être sauvegardé et distribué. En
conditions réelles, vous utiliserez donc souvent votre éditeur de texte et créerez
des fichiers Python pour mener à bien des projets.

Dans ce cours, j’écrirai directement dans mon terminal pour vous montrer les
résultats d’instructions simples et nous ne créerons des fichiers que lorsque cela
sera nécessaire. Cependant, pour cette première leçon concrète, je voulais tout
de même vous montrer comment créer un fichier Python et comment exécuter ce
fichier.

Pour créer un fichier Python, nous allons déjà ouvrir notre éditeur de texte,
allons ouvrir un nouveau fichier et enregistrer ce fichier en lui donnant une
extension .py. On peut appeler ce fichier cours.py par exemple et l’enregistrer
dans un dossier Python sur notre bureau.

Ici, on commence par enregistrer notre fichier au format Python avant même
d’écrire un quelconque code car cela va permettre à notre éditeur de reconnaitre
le type de code qu’on souhaite écrire et d nous proposer des fonctionnalités
13
PYTHON

relatives à cela. Par ailleurs, il est possible que votre éditeur vous propose
d’installer des extensions spécifiques Python pour faciliter l’écriture, l’affichage
et le debugging de votre code. Si c’est le cas, n’hésitez pas à les installer.

Ensuite, ajoutez les lignes de code suivantes dans votre fichier (nous allons
expliquer par la suite ce qu’elles signifient) :

Exécuter un fichier Python

Pour exécuter un fichier Python et obtenir le résultat des opérations faites dans
ce fichier, commencez déjà par ouvrir votre invite de commande ou votre
terminal.

Ici, si vous avez bien ajouté Python au PATH, vous n’avez qu’à taper cours.py
pour exécuter le code du fichier “cours.py”. Si votre système possède plusieurs
versions de Python, comme c’est le cas sur Mac, il faudra préciser la version
utilisée : on tapera alors python3 cours.py.

Si Python n’a pas été ajouté au PATH, il va falloir préciser où le fichier se


trouve. Pour cela, on va commencer par taper la commande cd Desktop. La
commande cd signifie “change directory” (“changer de dossier”).

Ensuite, on n’a plus qu’à préciser l’emplacement de notre fichier par rapport à
notre bureau (Desktop), c’est à dire dans notre cas Python/cours.py (Mac) ou
Python\cours.py (Windows) pour exécuter notre fichier, en précisant
éventuellement également une version si plusieurs versions sont installées sur
notre système (python3 Python/cours.py pour Mac).
14
PYTHON

Exécuter du Python en tapant directement dans l’invite de commande ou le


terminal

L’interpréteur Python peut être utilisé de manière interactive, c’est-à-dire qu’on


va pouvoir directement lui fournir du code Python à exécuter et il nous renverra
les résultats immédiatement.

Cette fonctionnalité est très utile lorsqu’on souhaite tester rapidement des bouts
de code ou pour l’apprentissage.

Pour utiliser l’interpréteur Python de cette manière, on va déjà devoir l’appeler


depuis l’invite de commande ou le terminal. Pour cela, on écrit la commande
Python3.7 et on presse Entrée pour valider.

Ensuite, on a plus qu’à écrire nos différentes instructions et à presser Entrée afin
que l’interpréteur les interprète immédiatement.

Syntaxe de base de Python : indentation, commentaires et print()


15
PYTHON

Chaque langage informatique est basé sur une série de règles et de conventions.
La syntaxe d’un langage définit ses différents éléments et la façon dont on va
pouvoir et devoir les utiliser.

J’aimerais pour le moment m’arrêter sur deux éléments de syntaxe de base que
sont les commentaires et l’indentation ainsi que sur la fonction print().

Les commentaires Python

Les commentaires sont des éléments de langage qu’on retrouve dans de


nombreux langages de programmation.

Les commentaires servent à “commenter” le code : ils vont être ignorés lors de
l’exécution du code (ils n’auront aucun impact sur le script) et vont donc être
totalement transparents pour l’utilisateur final.

On utilise généralement les commentaires pour documenter un code (pour soi ou


pour d’autres développeurs si le code a vocation à être distribué) ou pour
empêcher son exécution. En Python, on utilise le signe # pour écrire un
commentaire dans notre code.

Python n’a pas de syntaxe particulière pour écrire des commentaires multi-
lignes. Pour écrire un commentaire sur plusieurs lignes, on insérera un # au
début de chaque ligne.

L’indentation Python

L’indentation correspond au fait de créer des retraits au niveau de certaines


lignes de code. Dans la grande majorité des langages, l’indentation n’a qu’une
visée esthétique : elle permet à un script d’être plus lisible pour un développeur.

Généralement, une bonne indentation est censée représenter les dépendances au


sein d’un code : on ajoutera un retrait à chaque fois qu’une instruction est
incluse / dépend d’une autre.

En Python, l’indentation a un tout autre rôle : elle est utilisée par Python pour
définir des blocs de code, c’est-à-dire pour indiquer à l’interpréteur quelle
instruction appartient à quelle autre.

Si on indente mal notre code Python, celui-ci ne s’exécutera tout simplement pas
et Python renverra une erreur. Pas de panique, nous allons apprendre au cours de
ce cours à quelle moment indenter. Cela est cependant relativement évident et ne
devrait pas vous poser de problème : dès qu’il y a une relation de dépendance, il
faudra ajouter un retrait (une fabulation).
16
PYTHON

Dans le code ci-dessus, par exemple, nous avons utilisé une structure
conditionnelle if. Le principe de cette structure est simple : on lui fournit un test
et SI le test est validé, alors on exécute un code. Le code à exécuter dépend du
résultat du test; on effectuera donc un retrait pour mentionner ce code afin que
Python puisse bien s’apercevoir qu’il dépend de la structure conditionnelle.

Si vous avez l’habitude d’autres langages de programmation comme le PHP par


exemple cela peut être un peu déconcertant au départ. Vous pouvez alors
considérer que l’indentation remplace l’usage des accolades.

La fonction print()

Les fonctions sont d’autres éléments de langage que nous étudierons plus tard.
Grosso-modo, une fonction est définie par un nom et une série d’instructions.
Lorsqu’on appelle une fonction (en utilisant son nom et un couple de
parenthèses juste derrière), elle exécute toutes les instructions qu’elle contient.
Les fonctions servent généralement à effectuer une action précise qui peut être
plus ou moins complexe.

La fonction print() permet tout simplement d’afficher le message qu’on va lui


passer entre ses parenthèses. A première vue, la fonction print() ne parait pas
très utile, et c’est pourtant l’une des fonctions qu’on utilisera le plus.

En effet, cette fonction va être très précieuse puisqu’elle va également nous


permettre d’afficher des résultats auquel on n’a pas directement accès. Nous
illustrerons cela dans la suite de ce cours; faites moi confiance pour le moment.
17
PYTHON

CHAPITRE 1. LES VARIABLES ET


LES TYPES DE VALEURS PYTHON
1.1 Les variables Python

1.2 Les types de données ou types de valeurs Python

1.3 Les opérateurs Python

1.4 Les listes Python

1.5. Les tuples Python

1.6 Les dictionnaires Python

1.7 Les ensembles ou sets Python

1.1. Les variables Python


Dans cette leçon, nous allons découvrir un élément fondamental des langages de
programmation : les variable. Nous allons expliquer ce que sont les variables en
informatique, les usages qu’on va pouvoir en faire et comment créer des
variables Python.

1.1.1 Qu’est-ce qu’une variable ?


18
PYTHON

Une variable, dans le domaine de la programmation informatique, est un


conteneur qui sert à stocker une valeur. Les variables possèdent deux
caractéristiques fondamentales :

 Les variables ont une durée de vie limitée (une variable ne vit
généralement que le temps de l’exécution d’un script ou de la fonction qui
l’a définie), ce qui signifie qu’on ne va pas pouvoir utiliser les variables
pour stocker des données de manière pérenne ;
 La valeur d’une variable peut varier : les variables peuvent peuvent
stocker différentes valeurs au cours de leur vie (la nouvelle valeur
remplaçant l’ancienne).

Les variables donc être au coeur de nos scripts puisqu’elles vont nous permettre
de conserver des valeurs le temps d’un script et d’effectuer toutes sortes de
manipulations sur ces valeurs en toute simplicité.

1.1.2 Comment déclarer une variable en Python ?

Python ne possède pas de syntaxe particulière pour créer ou “déclarer” une


variable : les variables Python sont automatiquement créées au moment où on
leur assigne une valeur.

Pour créer une variable en Python, on va donc devoir choisir un nom et affecter
une valeur à ce nom, c’est-à-dire stocker une valeur dans notre variable.

Le choix du nom pour nos variables est libre en Python. Il faut cependant
respecter les règles usuelles suivantes :

 Le nom doit commencer par une lettre ou par un underscore ;


 Le nom d’une variable ne doit contenir que des caractères
alphanumériques courants (pas d’espace dans le nom d’une variable si de
caractères spéciaux comme des caractères accentués ou tout autre signe) ;
 On ne peut pas utiliser certains mots qui possèdent déjà une signification
spéciale pour le langage (on parle de mots “réservés”).

Notez que les noms de variables en Python sont sensibles à la casse, ce qui
signifie qu’on va faire une différence entre l’emploi de majuscules et de
minuscules : un même nom écrit en majuscules ou en minuscules créera deux
variables totalement différentes.

Pour affecter ou “assigner” une valeur à une variable, nous allons utiliser un
opérateur qu’on appelle opérateur d’affectation ou d’assignation et qui est
19
PYTHON

représenté par le signe =. Attention, le signe = ne signifie pas en informatique


l’égalité d’un point de vue mathématique : c’est un opérateur d’affectation.

Le signe = ne sert pas à dire que la valeur est égale au nom de variable ou que la
variable “vaut” cette valeur, il indique simplement qu’on affecte ou qu’on stocke
une certaine valeur dans un conteneur.

D’un point de vue mathématique, par exemple, écrire x = x + 2 n’a aucun sens
car la variable x ne peut être égale qu’à elle même. En informatique, cependant,
c’est tout à fait possible puisque l’opérateur = n’est pas un opérateur d’égalité
mais d’affectation. Ecrire x = x + 2 signifie qu’on affecte une nouvelle valeur à
x qui est égale à l’ancienne valeur de x à laquelle on ajoute 2.

Notez déjà qu’on va également pouvoir effectuer des affectations multiples en


Python, c’est-à-dire affecter plusieurs valeurs à plusieurs variables très
facilement en utilisant la syntaxe nom_variable_1, nom_variable_2,
nom_variable_3 = valeur1, valeur2, valeur3.

Que peut stocker une variable Python ?

Les variables vont pouvoir stocker différents types de valeurs comme des
nombres, des chaines de caractères, des booléens, et plus encore.

Il est important de connaitre le type de valeur stocké dans une variable car nous
n’allons pas pouvoir effectuer les même opérations avec une variable qui stocke
un nombre ou avec une variable qui stocke une chaine de caractères par
exemple.
20
PYTHON

Nous étudierons les spécificités liées à chaque type de valeur que peut stocker
une variable Python dans la prochaine leçon.

1.1.3 Afficher et modifier le contenu d’une variable Python

Nous allons pouvoir réaliser toutes sortes d’opérations avec nos variables. La
plus basique d’entre elles consiste à afficher le contenu d’une variable. Pour
afficher la valeur d’une variable Python, il suffit d’écrire son nom, ou
éventuellement d’utiliser la fonction print() en renseignant le nom de la variable
entre les parenthèses/

Comme je l’ai précisé plus haut, l’une des caractéristiques fondamentales des
variables va être de pouvoir stocker différentes valeurs durant sa vie. Ainsi, on
peut tout à fait affecter une nouvelle valeur à une variable. Une variable «
classique » ne va pouvoir stocker qu’une valeur à la fois. En affectant une
nouvelle valeur à une variable, la valeur précédente est ainsi écrasée.
21
PYTHON

Pour comprendre ce code, vous devez savoir qu’ici les instructions sont
exécutées linéairement, c’est-à-dire dans leur ordre d’écriture. On commence
par affecter la valeur 29 à notre variable age et la valeur Pierre à notre variable
prenom, puis on affiche le contenu de ces variables.

On affecte ensuite de nouvelles valeurs dans nos variables. Ces nouvelles


valeurs remplacent (“écrasent”) les précédentes. Lorsqu’on affiche à nouveau le
contenu de nos variables, les valeurs renvoyées sont les dernières stockées.

1.1.4 Quelle est l’utilité des variables Python ?

Les variables sont des éléments de base présents dans la quasi-totalité des
langages de programmation car elles vont s’avérer indispensables dans de très
nombreuses situations.

Il est difficile à ce niveau du cours d’illustrer concrètement la puissance des


variables. Le grand intérêt des variables va résider dans le fait qu’on va disposer
d’un nom fixe (un “label”) qui va nous servir à manipuler des valeurs qui
peuvent changer ou qu’on peut ne pas encore connaitre.

Imaginons par exemple qu’on crée un programme qui va effectuer des calculs à
partir d’une valeur qui va lui être envoyée uniquement lorsque ce programme
sera exécuté. Lors de la création du programme, on ne connait pas cette valeur et
cette valeur va pouvoir être différente entre différentes exécutions du
programme.

On va pouvoir indiquer que cette valeur (inconnue pour le moment) devra être
stockée dans telle variable au début du programme et ensuite définir les
différentes opérations qui devront être effectuées sur cette valeur en utilisant le
nom de la variable (qui sera remplacée par sa valeur effective lorsque le
programme s’exécutera).Les types de données ou types de valeurs Python

Dans cette leçon, nous allons définir ce qu’est un type de données et passer en
revue les types de données Python les plus courants et simples à appréhender.

1.2 Les types de données ou types de valeurs Python

1.2.1 Qu’est-ce qu’un type de données ?


22
PYTHON

En programmation, les données qu’on va pouvoir manipuler avec un langage


sont généralement classées par “type”.

Un “type” de données pour un langage est défini par les manipulations qu’on va
pouvoir faire sur ces données : on va pouvoir effectuer les mêmes opérations sur
chaque donnée d’un même type et des opérations différentes sur différents types
de données.

Prenons un nombre entier par exemple. Il semble tout à fait logique de pouvoir
effectuer des opérations mathématiques de base avec ce nombre : addition,
soustraction, multiplication, etc. En revanche, on ne va pas pouvoir effectuer les
mêmes opérations / manipulations sur un texte, puisque multiplier un texte par
quelque chose par exemple n’a aucun sens.

1.2.2 Les types de données Python

Python définit de nombreux types de données qu’on va pouvoir stocker dans nos
variables et manipuler à loisir ensuite : nombres entiers, décimaux, complexes,
chaines de caractères, booléens, listes, tuples, dictionnaires, etc.

Dans cette leçon, nous allons nous contenter de passer en revue les types de
données les plus simples à se représenter (nombres, chaines et booléens). Les
autres types de données feront l’objet de leçons séparées.

1.2.3 Les types numériques int, float et complex

Python définit trois types de valeurs numériques supportées :

 Le type int qui représente tout entier positif ou négatif ;


 Le type float qui représente les nombres décimaux et certaines
expressions scientifiques comme le e pour désigner une exponentielle par
exemple;
 Le type complex qui représente les nombres complexes ou nombres
imaginaires et qui se sert de la lettre j pour représenter la partie imaginaire
d’un nombre.

Le type de données “nombre entier” ou int pour être technique (“int” = “integer”
= entier) couvre tous les nombres entiers positifs ou négatifs. On va pouvoir
effectuer toutes sortes d’opérations arithmétiques avec ce premier type de
23
PYTHON

données : addition, soustraction, multiplication, division, élévation à la


puissance, etc.

Pour effectuer des opérations arithmétiques entre différentes valeurs numérique,


nous allons devoir utiliser des opérateurs arithmétique (+ pour l’addition, - pour
la soustraction, etc.).

On va pouvoir effectuer ces opérations directement entre nombres et se servir de


Python comme d’une calculatrice ou affecter ces nombres à des variables et
utiliser nos variables pour effectuer nos opérations :

Ici, on commence par effectuer des opérations entre nombres : addition,


soustraction, multiplication, division et élévation à la puissance. Notez que pour
réaliser une division entière, on utilise l’opérateur //. On peut également utiliser
l’opérateur / pour réaliser une division “classique” mais dans ce cas le résultat
sera toujours considéré comme étant de type float (nombre décimal).
Finalement, on utilise l’opérateur ** pour élever un nombre à la puissance.

On peut également stocker des nombres dans des variables et utiliser ces
variables pour effectuer nos calculs. Ici, on commence par définir une variable x
et on lui attribue la valeur 5. On effectue ensuite différentes opérations. Notez
que durant tous ces calculs x continue de stocker 5 puisqu’on n’affecte jamais de
nouvelles valeurs à x. Finalement, on définit une deuxième variable y = 10 et on
demande à Python de calculer x + y, c’est-à-dire de nous donner le résultat de
l’addition des deux valeurs contenues dans x et dans y.
24
PYTHON

Le type de données “nombre décimal” ou float couvre tous les nombres


décimaux (c’est-à-dire les nombres à virgule) ainsi que certaines expressions
scientifiques comme le e qui désigne une exponentielle.

Attention ici : dans le monde de la programmation, les notations anglo-saxonnes


sont la norme. Il faudra donc bien faire attention à utiliser un . et non pas une ,
pour les décimaux.

Nous allons grosso-modo pouvoir réaliser les mêmes opérations avec des
données de type float qu’avec des données de type int (même si le traitement en
arrière plan va être différent).

Il y a différentes choses à noter par rapport au type float en Python :

 Toute opération arithmétique entre nombres de type float donne un


résultat de type float ;
 Toute opération arithmétique entre nombres de types int et float donne un
résultat de type float ;
 La division classique donne toujours un résultat de type float.

On effectue plusieurs opérations arithmétiques d’un coup sur nos dernières


lignes dans l’exemple ci-dessus. Dans ce cas là, il faudra faire attention à l’ordre
des opérations. L’ordre des opérations va être le même qu’en mathématiques :
les calculs de puissance seront effectués en priorité, puis la multiplication et la
division, puis enfin l’addition et la soustraction.
25
PYTHON

On va également pouvoir utiliser des parenthèses pour imposer un ordre de


priorité de calculs différents. Dans ce cas là, ce qui se trouve entre parenthèses
sera calculé en premier.

Finalement, le type de données “nombre complexe” ou complex représente les


nombres complexes. On va utiliser la lettre j ou J pour représenter la partie
complexe d’un nombre. Comme la plupart d’entre vous n’auront que rarement
affaire aux nombres complexes et que ce cours n’est pas un cours de
mathématiques, je n’entrerai pas dans le détail ici.

1.2.4 Le type str ou chaine de caractères

Les chaines de caractères sont ce qu’on appelle communément du texte. Pour


définir une chaine de caractères ou pour stocker une chaine de caractères dans
une variable, il faudra l’entourer de guillemets simples ou doubles droits.

Si notre chaine de caractères contient elle même des guillemets simples


(apostrophes) ou doubles, il faudra les échapper les uns ou les autres en fonction
du délimiteur choisi pour qu’ils soient correctement interprétés car sinon Python
pensera qu’ils servent à indiquer la fin de la chaine. Le caractère d’échappement
en Python est l’antislash \.
26
PYTHON

Dans l’exemple ci-dessus, on veut afficher et stocker la chaine Je m’appelle


“Pierre Giraud” qui contient à la fois des guillemets simples ou apostrophes et
des guillemets doubles. Il va donc falloir qu’on échappe les uns ou les autres en
fonction du caractère de délimitation de chaine choisi afin d’indiquer au Python
que les guillemets simples ou doubles à l’intérieur de notre chaine ne
représentent pas la fin de la chaine, c’est-à-dire pour lui indiquer qu’ils ne
possèdent pas ce sens spécial de délimiteurs.

Notez qu’on peut également utiliser une syntaxe alternative utilisant des triples
guillemets simples ou doubles pour entourer notre chaine et qui nous dispense
ainsi d’avoir à échapper les apostrophes et les guillemets dans notre chaine :

Lorsqu’on utilise l’interpréteur en mode interactif, comme on le fait dans ce


cours, l’interpréteur affiche les chaines entre guillemets simples. On peut utiliser
la fonction print() pour afficher les chaînes de manière plus lisible, en retirant
notamment les guillemets simples et doubles :
27
PYTHON

J’ai dit plus haut que pour définir une chaine de caractères il fallait l’entourer de
guillemets simples ou doubles droits. Réciproquement, toute valeur entourée par
des guillemets simples ou doubles sera considéré par Python comme une valeur
de type str (“str” = “string” = chaine de caractères).

Ainsi, si on stocke un ou plusieurs caractères représentant des chiffres comme


“1”, “2”, “123”, etc. en les entourant de guillemets simples ou doubles ceux-ci
seront considérés comme des valeurs de type str et non comme des valeurs de
type int, code>float ou complexe et on ne pourra pas effectuer les mêmes
opérations.

Comme vous pouvez le voir, on n’obtient pas du tout les mêmes résultats
lorsqu’on additionne deux nombres ou lorsqu’on additionne (ou plus exactement
concatène) deux chaines.

Lorsqu’il est utilisé avec deux chaines, l’opérateur + est un opérateur de


concaténation et pas d’addition. “Concaténer” signifie “mettre bout à bout”.
Nous reparlerons de ce concept dans la prochaine leçon.

Finalement, vous pouvez également remarquer que Python nous renvoie une
erreur lorsqu’on tente d’additionner / de concaténer un entier avec une chaine.

1.2.5 Le type de valeurs bool ou booléen

Le dernier type de valeurs simple Python que je tenais à vous présenter est le
type bool (pour “booléen”).

Le type de valeur booléen est un type qui ne contient que deux valeurs qui
servent à représenter deux états. Les deux valeurs sont True (vrai) et False
28
PYTHON

(faux). Attention en Python à bien indiquer des majuscules car dans le cas
contraire Python ne reconnaitra pas ces booléens.

Pour stocker un booléen dans une variable, il ne faut pas utiliser de guillemets :
si on les utilise, ce seront les chaines de caractères “True” et “False” qui seront
stockés et on ne va pas pouvoir effectuer les mêmes opérations.

Les valeurs booléennes sont très utilisées en informatique. Elles sont notamment
très utiles pour valider ou invalider un test et sont au coeur des différentes
structures de contrôle en général.

1.2.6 Utiliser la fonction type() pour connaitre le type d’une valeur

On voudra souvent s’assurer qu’une variable contient bien une valeur d’un
certain type, notamment pour pouvoir effectuer différentes manipulations avec
cette variable.

Pour connaitre le type de valeur stockée dans une variable, on peut utiliser la
fonction Python type(). On va passer la variable à tester en argument de cette
fonction (c’est-à-dire écrire le nom de la variable entre les parenthèses de la
fonction). La fonction type() va alors tester la valeur contenue dans la variable et
renvoyer le type de cette valeur.
29
PYTHON

Ne faites pas attention pour le moment à l’indication “class” également


renvoyée par la fonction type(), nous verrons ce que ça signifie bien plus tard
dans ce cours.

1.3 Les opérateurs Python


Dans cette nouvelle leçon, nous allons définir ce qu’est un opérateur, établir la
liste des types d’opérateurs disponibles en Python et apprendre à en manipuler
certains.

1.3.1 Définition et liste des opérateurs Python

Un opérateur est un signe ou un symbole qui va nous permettre de réaliser une


opération. Le signe = par exemple est en Python l’opérateur d’affectation simple
: il permet d’affecter une valeur à une variable.

Python dispose de nombreux opérateurs qui peuvent être classés selon les
catégories suivantes :

 Les opérateurs arithmétiques ;


 Les opérateurs d’affectation ou d’assignation ;
 Les opérateurs de chaines ;
 Les opérateurs de comparaison ;
 Les opérateurs logiques ;
 Les opérateurs d’identité ;
 Les opérateurs d’appartenance ;
 Les opérateurs binaires.

Dans cette leçon, nous allons nous concentrer sur les opérateurs arithmétiques,
les opérateurs de chaines et sur les opérateurs d’affectation.

Nous étudierons les autres types d’opérateurs plus tard dans ce cours, lorsque
nous n aurons besoin pour illustrer certaines notions de Python.

1.3.2 Les opérateurs arithmétiques

Les opérateurs arithmétiques sont utilisés pour effectuer des opérations


mathématiques comme des additions, soustractions, multiplication, etc. entre
différentes variables contenant des valeurs numériques.

Python reconnait et accepte les opérateurs arithmétiques suivants :


30
PYTHON

Opérate
Nom
ur
+ Addition
– Soustraction
* Multiplication
/ Division
% Modulo
** Puissance
Division
//
entière

Certains opérateurs nécessitent certainement qu’on s’attarde dessus.

Le modulo correspond au reste d’une division Euclidienne (division entière)


tandis que l’opérateur // permet d’obtenir le résultat entier d’une division (ou la
partie entière de ce résultat pour être tout à fait exact).

Le résultat de 13//3, par exemple, sera 4 tandis que le résultat de 13%3 sera 1 car
dans le cas d’une division entière 13/3 = 4 avec reste = 1.

L’opérateur puissance permet d’élever le nombre à gauche de l’opérateur à une


certaine puissance mentionnée à droite de l’opérateur. La “puissance”
correspond à la multiplication d’un nombre par lui même. Par exemple, écrire 2
** 4 correspond à multiplier 2 par lui-même 4 fois ( = 2 * 2 * 2 * 2 = 16).

1.3.3 Les opérateurs de chaines


31
PYTHON

Les opérateurs de chaines vont nous permettre de manipuler des données de type
str (chaines de caractères) et par extension des variables stockant des données de
ce type.

Python met à notre disposition deux opérateurs de chaine : l’opérateur de


concaténation + et l’opérateur de répétition *.

L’opérateur de concaténation va nous permettre de mettre bout à bout deux


chaines de caractères afin d’en former une troisième, nouvelle.

L’opérateur de répétition va nous permettre de répéter une chaine un certain


nombre de fois.

Ces deux symboles remplissent donc un rôle relativement similaire que


lorsqu’ils sont utilisés avec des données de type numériques mais attention tout
de même de ne pas confondre le + utilisé pour additionner deux nombres et le +
utilisé pour concaténer deux chaines de caractères : on distingue ici bien deux
opérateurs différents même si le même symbole est utilisé.

1.3.4 Les opérateurs d’affection simple et composés Python

Nous connaissons déjà bien l’opérateur d’affectation simple Python =. Cet


opérateur permet d’affecter ou d’assigner une valeur à une variable.

Python reconnait également des opérateurs d’affectation qu’on appelle


“composés” et qui vont nous permettre d’effectuer deux opérations à la suite :
32
PYTHON

une première opération de calcul suivie immédiatement d’une opération


d’affectation.

Ces opérateurs vont donc nous permettre de réduire la taille de notre code en
nous offrant une écriture simplifiée. Voici la liste des opérateurs d’affectation
supportés par Python et leur équivalent en “version longue” :

Opérate Equivalent
Exemple Description
ur à
= x=1 x=1 Affecte 1 à la variable x
Ajoute 1 à la dernière valeur connue de x et affecte la
+= x += 1 x=x+1
nouvelle valeur (l’ancienne + 1) à x
Enlève 1 à la dernière valeur connue de x et affecte la
-= x -= 1 x=x–1
nouvelle valeur à x
Mutliplie par 2 la dernière valeur connue de x et
*= x *= 2 x=x*2
affecte la nouvelle valeur à x
Divise par 2 la dernière valeur connue de x et affecte
/= x /= 2 x=x/2
la nouvelle valeur à x
Calcule le reste de la division entière de x par 2 et
%= x %= 2 x = x % 2
affecte ce reste à x
Calcule le résultat entier de la division de x par 2 et
//= x //= 2 x = x // 2
affecte ce résultat à x
Elève x à la puissance 4 et affecte la nouvelle valeur
**= x **= 4 x = x ** 4
dans x

Vous pouvez également déjà noter qu’il existe également les opérateurs
d’affectation combinés &=, |=, ^=, >>= et <<= qui vont permettre d’effectuer
des opérations dont nous discuterons plus tard et d’affecter le résultat de ces
opérations directement à une variable.

Entrainons nous immédiatement avec ces opérateurs pour commencer à se


familiariser avec eux :
33
PYTHON

1.4 Les listes Python


Dans cette leçon, nous allons découvrir un premier type de données composites
Python : les listes. Nous allons comprendre l’intérêt de ce type de données et
apprendre à les manipuler.

1.4.1 Présentation des listes Python

Jusqu’à présent, nous n’avons stocké qu’une seule valeur à la fois dans nos
variables. Les listes sont un type de données très particulier au sens où elles
représentent des données composées ou combinées. Une liste est en effet par
définition composée d’une suite de valeur ou d’éléments.

Pour définir une nouvelle liste en Python, on va devoir utiliser une paire de
crochets [ ]. Nous allons placer les différents éléments de notre liste dans ces
crochets en les séparant par des virgules. On peut par exemple créer une liste de
5 éléments et la placer dans une variable liste comme ceci :

Notre liste est ici composée de 5 valeurs de type numérique. On va pouvoir


stocker tous types de valeurs dans une liste, comme des chaines de caractères
par exemple :

De plus, vous devez savoir que tous les éléments d’une liste n’ont pas à être du
même type, on va très bien pouvoir créer des listes composées de nombres,
chaines et booléens par exemple :

Note : Si vous avez déjà étudié un langage de script par le passé, les liste doivent
vous faire penser à ce qu’on appelle communément dans ces autres langages des
tableaux. En effet, les listes Python sont très proches des tableaux (numérotés)
qu’on peut retrouver dans de nombreux autres langages.
34
PYTHON

1.4.2 Récupérer une ou plusieurs valeurs dans une liste

Les listes Python sont par défaut indexées ou indicées. Cela signifie que chaque
valeur d’une liste est lié à un indice qu’on va pouvoir utiliser pour récupérer
cette valeur en particulier.

Les listes possèdent des indices numériques qui commencent à 0. La première


valeur d’une liste possède donc toujours l’indice 0, la deuxième valeur l’indice
1, la troisième valeur l’indice 2 et etc.

Pour récupérer une valeur en particulier dans une liste, on va devoir préciser le
nom de la liste suivi de l’indice de cette valeur entre crochets. Notez que les
indices négatifs sont acceptés; dans ce cas on partira de la fin de la liste (l’indice
-1 correspond au dernier élément, -2 à l’avant dernier et etc.).

On va également pouvoir récupérer une tranche de valeurs dans une liste, c’est-
à-dire un ensemble de valeurs qui se suivent. Pour cela, on utilisera le symbole :
entre les crochets avec 0, 1 ou 2 indices autour.

Si on utilise : sans indice, alors une copie superficielle de la liste sera renvoyée.
Si on mentionne un indice avant : mais pas d’indice après, alors une copie
superficielle partielle de la liste de départ sera renvoyée, en commençant à
copier à partir de l’indice donné. Si au contraire on mentionne un indice après :
mais pas d’indice avant, une copie superficielle partielle de la liste de départ sera
renvoyée qui commence au début de la liste et jusqu’à l’indice donné. Enfin, si
deux indice sont mentionnés de part et d’autre de :, la tranche de valeurs
correspondant à ces indices sera renvoyée.
35
PYTHON

Vous devez également savoir que ce qu’on a vu jusqu’ici sur les listes
s’applique également aux chaines de caractères. Les chaînes de caractères
peuvent en effet également être indexées, ce qui signifie qu’on peut accéder aux
caractères par leur position). Cela est logique après tout : les chaines de
caractères sont des “séquences” de caractères tandis que les listes sont des
“séquences” de valeurs.

Comme pour les listes, le premier caractère d’une chaîne possède l’indice 0, le
deuxième l’indice 1 et etc; On va également pouvoir utiliser des indices négatifs
et récupérer des tranches avec :.

Notez qu’il n’existe pas de type distinct pour les caractères en Python : un
caractère est simplement une chaîne de longueur 1.

1.4.3 Ajouter, supprimer, modifier des éléments d’une liste

A la différence des types de données simples comme les chaines qui sont
immuables, les listes sont un type de données altérable ce qui signifie qu’on va
pouvoir altérer leur structure ou modifier leur contenu en ajoutant, supprimant
ou remplaçant des valeurs.
36
PYTHON

En effet, vous devez bien comprendre qu’une fois qu’on définit une valeur
“chaine de caractères” par exemple, celle-ci ne peut plus être modifiée par la
suite. Les seules opération qu’on va pouvoir faire vont être de créer une nouvelle
chaine en concaténant deux chaines d’origine (qui une nouvelle fois ne seront
pas modifiées) ou de remplacer une chaine par une autre valeur en affectant une
nouvelle valeur dans une variable (ce qui a pour effet d’écraser la chaine de
départ).

Au contraire des chaines, on va tout à fait pouvoir ajouter, modifier ou


supprimer des valeurs dans une liste. Pour cela, on va mentionner le nom de
notre liste avec l’indice de la ou des éléments à ajouter / modifier et leur affecter
une nouvelle valeur. Les affectations de tranches sont possibles :

Notez finalement également qu’on va aussi pouvoir utiliser les opérateurs de


concaténation et de répétition avec des listes :

1.5 Les tuples Python


Dans cette leçon, nous allons nous intéresser à un nouveau type de données
composites Python qui peut faire penser aux listes à premières vue : les tuples.
37
PYTHON

Nous allons souligner les différences entre les listes et les tuples, voir les cas
d’usage des tuples et apprendre à créer des tuples.

1.5.1 Présentation des tuples et cas d’utilisation

Les chaines de caractères et les listes sont deux types séquentiels de données : ce
sont des données qui sont organisées sous la forme de séquence de caractères ou
de valeurs. Les tuples sont un autre type séquentiel de données.

Les tuples ressemblent aux listes : un tuple consiste en différentes valeurs


entourées par des virgules. Notez qu’on encadre généralement les valeurs d’un
tuple avec un couple de parenthèses même si cela n’est pas obligatoire.

Les tuples peuvent contenir différents types de valeurs comme des nombres, des
chaines, des listes etc. et même d’autres tuples imbriqués. Illustrons
immédiatement cela :

La grande différence entre un tuple et une liste est qu’un tuple est une donnée
immuable à la différence d’une liste qui est altérable. Cela signifie qu’on ne va
pas pouvoir modifier les valeurs d’un tuple après sa création.

Il va donc être intéressant d’utiliser des tuples plutôt que des listes dans les cas
où on veut s’assurer que les données ne soient pas modifiées dans un
programme.

1.5.2 Création d’un tuple vide ou à une valeur

Notez que dans le cas où on souhaite créer un tuple vide, on utilisera une paire
de parenthèses vides. Si on souhaite créer un tuple avec une seule valeur, alors il
faudra faire suivre cette valeur d’une virgule.
38
PYTHON

1.5.3 Le déballage de séquence

Une fonctionnalité intéressante des tuples est le “déballage de séquence”. Un


déballage de séquence correspond à une façon rapide d’affecter les différentes
valeurs d’un tuple dans des variables séparées. Pour cela, il va nous falloir
autant de variables qu’il y a de valeurs dans notre tuple. Ensuite, il va falloir
respecter la syntaxe variable1, variable2 … = tuple comme ceci :

Attention ici : il faut bien faire attention à écrire les variables qui vont recevoir
les valeurs du tuple avant le tuple car dans le cas contraire cela ne fonctionnerait
pas.

1.6 Les dictionnaires Python


Dans cette leçon, nous allons nous intéresser à un autre type de données Python
composites : les dictionnaires. Nous allons découvrir l’intérêt des dictionnaires
et apprendre à manipuler ce nouveau type de données.

1.6.1 Présentation des dictionnaires Python

Les dictionnaires sont un type natif de données Python. Ce type de données


peut, de la même façon que les données séquentielles, contenir plusieurs valeurs
et chaque valeur va être indexée ce qui signifie qu’un indice unique va être
attribué à chaque valeur.
39
PYTHON

La grande différence entre les données séquentielles et les dictionnaires se situe


dans la façon d’indexer les valeurs et dans la nature de l’index. Dans le cas des
séquences, les différentes valeurs dont associées à des index numériques
commençant à 0.

Les dictionnaires nous laissent une bien plus grande liberté ici puisqu’on va
pouvoir choisir nous mêmes nos clefs (ou index ou indice) et attribuer la clef de
notre choix à chaque valeur à partir du moment où cette clef n’est pas déjà
utilisée dans ce dictionnaire et où la clef est une valeur immuable. La
conséquence de cela est que les valeurs d’un dictionnaire ne sont pas ordonnées
à la différence des valeurs d’une séquence.

Si vous avez des notions en PHP ou dans certains autres langages de script, vous
pouvez retenir que les dictionnaires Python sont l’équivalent des tableaux
associatifs dans ces langages.

1.6.2 Création d’un dictionnaire Python

Pour créer un nouveau dictionnaire, nous allons devoir utiliser un couple


d’accolades { } et définir les paires clef : valeur à l’intérieur des accolades
comme ceci :

Comme vous pouvez le voir dans l’exemple ci-dessus, on utilise une nouvelle
fois le syntaxe avec des crochets pour lire les différentes valeurs de notre
dictionnaire. Pour être tout à fait précis, on passe ici une clef entre crochets pour
récupérer la valeur qui lui est associée.

1.6.3 Ajout et modification de valeurs dans un dictionnaire

Les dictionnaires sont altérables, ce qui signifie qu’on va pouvoir modifier ou


ajouter des valeurs dans un dictionnaire après sa création.

Pour cela, on va tout simplement utiliser le nom de notre dictionnaire suivi d’un
couple de crochets [ ] en passant une clef entre ces crochets puis affecter une
40
PYTHON

valeur à cette clef. Dans le cas où la clef existe déjà, l’ensemble clef : valeur
n’est pas ajouté mais la valeur originellement liée à la clef est plutôt remplacée
par la nouvelle valeur.

Illustrons immédiatement cela avec quelques exemples de manipulation des


données de dictionnaires Python :

Pour supprimer une paire clef : valeur d’un dictionnaire, nous allons utiliser
l’instruction del (abréviation de “delete” = supprimer en anglais) suivi du nom
du dictionnaire avec la clef de l’élément à supprimer entre crochets comme
ceci :

1.7 Les ensembles ou sets Python


Dans cette leçon, nous allons voir un nouveau type de données Python : les
ensembles ou “set”. Nous allons découvrir l’intérêt de ce type de données et
comment créer des ensembles Python.

1.7.1 Présentation des ensembles ou sets Python

Les ensemble ou sets forment un autre type de données composites Python. Un


ensemble est une collection d’éléments non ordonnée, sans index et qui ne peut
pas posséder l’élément dupliqué.
41
PYTHON

Une des utilisation les plus courantes des ensembles est de les utiliser pour
supprimer des valeurs doublons à partir d’un autre type de données.

Pour créer un ensemble, nous allons utiliser une paire d’accolades { } en placer
les différents éléments de notre ensemble entre ces accolades en les séparant
avec une virgule.

Notez que pour créer un ensemble vide il faudra utiliser la fonction set() car la
syntaxe { } va créer un dictionnaire vide et non pas un ensemble vide.

1.7.2 Récapitulatif sur les types de données et sur les types composites
Python

Dans cette partie, nous avons étudié des types de données simples et des types
de données composites (des données composées de plusieurs éléments) Python.

Les types de données simples étudiés sont les Nombre (entier, décimaux ou
complexes), les Booléens et les Chaines de caractères. Il sont facile à manier et
il est simple de savoir quand utiliser une type plutôt qu’un autre.

Les types de données composite étudiés sont les listes, les tuples, les
dictionnaires et les ensembles. Il est généralement moins évident de choisir quel
type de données utiliser ici car on a tendance à penser “qu’ils se ressemblent
tous”.

Voici donc un résumé des grandes caractéristiques de ces types et se qui les
différencie :

 Les listes sont des collections d’éléments ordonnés et altérables qui


peuvent contenir plusieurs fois la même valeur ;
 Les tuples sont des collections d’éléments ordonnés et immuables qui
peuvent contenir plusieurs fois la même valeur ;
42
PYTHON

 Les dictionnaires sont des collection d’éléments non ordonnés mais


indexés avec des clefs de notre choix et altérables qui n’acceptent pas de
contenir plusieurs fois le même élément ;
 Les ensembles sont des collections d’éléments non ordonnées, non
indexés et non modifiables qui n’acceptent pas de contenir plusieurs fois
le même élément.
43
PYTHON

CHAPITRE 2. LES STRUCTURES DE


CONTRÔLE PYTHON
2.1 Les structures conditionnelles if, if…else et if…elif…else en Python

2.2 Créer des conditions Python complexes

2.3 Les boucles Python for et while

2.1 Les structures conditionnelles if, if…else et if…elif…else en Python


Dans cette nouvelle partie, nous allons étudier et comprendre l’intérêt des
structures de contrôle en Python. Une structure de contrôle est un ensemble
d’instructions qui permet de contrôler l’exécution du code.

Il existe différents types de structures de contrôle. Les deux types de structures


les plus communément utilisées sont les structures de contrôle conditionnelles
qui permettent d’exécuter un bloc de code si une certaine condition est vérifiée
et les structures de contrôle de boucle qui permettent d’exécuter un bloc de code
en boucle tant qu’une condition est vérifiée.

2.1.1 Présentation des conditions Python

Les structures de contrôle conditionnelles (ou plus simplement conditions) vont


nous permettre d’exécuter différents blocs de code selon qu’une condition
spécifique soit vérifiée ou pas.

Nous allons très souvent utiliser les conditions avec des variables : selon la
valeur stockée dans une variable, nous allons vouloir exécuter un bloc de code
plutôt qu’un autre.

Python nous fournit les structures conditionnelles suivantes :

 La condition if (“si”) ;
 La condition if…else (“si…sinon”) ;
 La condition if…elif…else (“si…sinon si… sinon”) .

Nous allons étudier et comprendre l’intérêt de chacune de ces conditions dans la


suite de cette leçon. Avant de les étudier, cependant, nous allons devoir
présenter un nouveau type d’opérateurs : les opérateurs de comparaison qui vont
être au centre de nos conditions.

2.1.2 Les opérateurs de comparaison


44
PYTHON

Comme je l’ai précisé plus haut, nous allons souvent construire nos conditions
autour de variables : selon la valeur d’une variable, nous allons exécuter tel bloc
de code ou pas.

Pour pouvoir faire cela, nous allons comparer la valeur d’une variable à une
certaine autre valeur donnée et selon le résultat de la comparaison exécuter un
bloc de code ou pas. Pour comparer des valeurs, nous allons devoir utiliser des
opérateurs de comparaison.

Voici ci-dessous les différents opérateurs de comparaison disponibles en Python


ainsi que leur signification :

Opérate
Définition
ur
== Permet de tester l’égalité en valeur et en type
!= Permet de tester la différence en valeur ou en type
Permet de tester si une valeur est strictement inférieure à une
<
autre
Permet de tester si une valeur est strictement supérieure à une
>
autre
<= Permet de tester si une valeur est inférieure ou égale à une autre
>= Permet de tester si une valeur est supérieure ou égale à une autre

Notez bien ici que ces opérateurs ne servent pas à indiquer à Python que telle
valeur est supérieure, égale, inférieur ou différente à telle autre valeur.
Lorsqu’on utilise un opérateur de comparaison, on demande au contraire à
Python de tester si telle valeur est supérieure, égale, inférieur ou différente à
telle autre valeur. Python va donc comparer les deux valeurs et toujours
renvoyer un booléen : True si la comparaison est vérifiée ou False dans le cas
contraire.

Notez également que les opérateurs de comparaison d’égalité et de différence


testent l’égalité et la différence à la fois sur les valeurs et sur les types. Ainsi, si
on demande à Python de tester l’égalité entre la chaine de caractères “4” et le
chiffre 4, celui-ci renverra False puisque pour lui ces deux valeurs ne sont pas
égales.

Regardez plutôt les exemples suivants pour vous en persuader :


45
PYTHON

Vous pouvez retenir ici que c’est cette valeur booléenne renvoyée par le Python
à l’issue de toute comparaison que nous allons utiliser pour faire fonctionner nos
conditions.

2.1.3 La condition if en Python

La structure conditionnelle if est une structure de base qu’on retourne dans de


nombreux langages de script. Cette condition va nous permettre d’exécuter un
code si (et seulement si) une certaine condition est vérifiée.

On va en fait passer une expression à cette condition qui va être évaluée par
Python. Cette expression sera souvent une comparaison explicite (une
comparaison utilisant les opérateurs de comparaison) mais pas nécessairement.

Si Python évalue l’expression passée à True, le code dans la condition if sera


exécuté. Dans le cas contraire, le code dans if sera ignoré.

Prenons immédiatement un premier exemple afin de nous familiariser avec le


fonctionnement et la syntaxe de cette condition :

Nous créons ici deux conditions if. Comme vous pouvez le voir, la syntaxe
générale d’une condition if est if condition : code à exécuter. Pensez bien à
46
PYTHON

indiquer le : et à bien indenter le code qui doit être exécuté si la condition est
vérifiée sinon votre condition ne fonctionnera pas.

Dans le premier if, nous demandons à Python dévaluer la comparaison x > y.


Comme notre variable x stocke 8 et que notre variable y stocke 4, Python valide
cette comparaison et renvoie True. La condition if reçoit True et le code qu’elle
contient est exécuté.

Dans notre deuxième if, on demande cette fois-ci à Python de nous dire si le
contenu de x est égal au chiffre 5. Ce n’est pas le cas et donc Python renvoie
False et le code dans ce if n’est donc pas exécuté.

Au final, vous pouvez retenir que toute expression qui suit un if va être évaluée
par Python et que Python renverra toujours soit True, soit False. Nous n’avons
donc pas nécessairement besoin d’une comparaison explicite pour faire
fonctionner un if.

Pour comprendre cela vous devez savoir qu’en dehors des comparaisons Python
évaluera à True toute valeur passée après if à l’exception des valeurs suivantes
qui seront évaluées à False :

 La valeur 0 (et 0.0) ;


 La valeur None ;
 Les valeurs chaine de caractères vide ””, liste vide [], dictionnaire vide {}
et tuile vide ().

2.1.4 La condition if… else en Python

Avec la condition if, nous restons relativement limités puisque cette condition
nous permet seulement d’exécuter un bloc de code si que le résultat d’un test
soit évalué à True.
47
PYTHON

La structure conditionnelle if…else (« si… sinon » en français) est plus


complète que la condition if puisqu’elle nous permet d’exécuter un premier bloc
de code si un test renvoie True ou un autre bloc de code dans le cas contraire.

La syntaxe d’une condition if…else va être la suivante :

Ici, on demande dans notre première condition à Python d’évaluer si la valeur de


x est différente du chiffre 5 ou pas. Si c’est le cas, Python renverra True
(puisqu’on lui demande ici de tester la différence et non pas l’égalité) et le code
du if sera exécuté. Dans le cas contraire, c’est le code du else qui sera exécuté.

Notre deuxième condition fait exactement le même travail mais cette fois si on
compare la valeur de yà 5.

Notez bien ici qu’on n’effectuera jamais de test dans un else car le else est par
définition censé prendre en charge tous les cas non pris en charge par le if.

2.1.5 La condition if… elif… else en Python

La condition if…elif…else (« si…sinon si…sinon ») est une structure


conditionnelle encore plus complète que la condition if…else qui vannons
permettre cette fois-ci d’effectuer autant de tests que l’on souhaite et ainsi de
prendre en compte le nombre de cas souhaité.

En effet, nous allons pouvoir ajouter autant de elif que l’on souhaite entre le if
de départ et le else de fin et chaque elif va pouvoir posséder son propre test ce
qui va nous permettre d’apporter des réponses très précises à différentes
situations.
48
PYTHON

Il faut cependant faire attention à un point en particulier lorsqu’on utilise une


structure Python if… elif… else : le cas où plusieurs elif possèdent un test
évalué à True par Python. Dans ce cas là, vous devez savoir que seul le code du
premier elif (ou du if si celui-ci est évalué à True) va être exécuté. En effet,
Python sort de la structure conditionnelle dans son ensemble sans même lire ni
tester la fin de celle-ci dès qu’un cas de réussite à été rencontré et que son code a
été exécuté.

2.2 Créer des conditions Python complexes

Dans cette nouvelle leçon, nous allons aller plus loin avec les conditions Python
est voir comment créer des conditions complexes en utilisant notamment les
opérateurs logiques et les opérations d’appartenance.

Imbriquer des conditions

Souvent, nous allons vouloir comparer plusieurs valeurs au sein d’une même
condition, c’est-à-dire n’exécuter son code que si plusieurs conditions sont
vérifiées.

Pour faire cela, nous allons pouvoir soit utiliser plusieurs opérateurs de
comparaison, soit les opérateurs logiques, soit imbriquer plusieurs conditions les
unes dans les autres.

Les opérateurs logiques vont nous permettre de créer des conditions plus
puissantes mais dans certains cas il sera plus intéressant et plus rapide
d’imbriquer des conditions.
49
PYTHON

Dans cet exemple, on imbrique deux structures if…else l’une dans l’autre. La
première structure demande à Python de tester si notre variable x contient un
nombre strictement inférieur à 5. Si c’est le cas, on rentre dans le if et on teste
donc la condition du deuxième if. Dans le cas contraire, on va directement au
else de fin.

Notre deuxième condition teste si y contient une valeur strictement inférieure à


10. Si c’est le cas, on exécute le code dans la condition. Sinon, on va
directement au else de cette condition imbriquée.

2.2.1 Utiliser les opérateurs logiques avec les conditions

Les opérateurs logiques vont être principalement utilisés avec les conditions
puisqu’ils vont nous permettre d’écrire plusieurs comparaisons au sein d’une
même condition ou encore d’inverser la valeur logique d’un test.

Opérate
Définition
ur

Renvoie True si toutes les deux expressions sont évaluées à


and
True

or Renvoie True si une des comparaisons vaut True

not Renvoie True si la comparaison vaut False (et inversement)

Les opérateurs logiques and et or vont nous permettre de passer plusieurs tests
pour évaluation à Python. On va par exemple pour tester si une variable x
contient une valeur inférieure à 5 et / ou si y contient une valeur inférieure à 10
au sein d’une même condition.

Dans le cas où on utilise and, chaque expression devra être évaluée à True par
Python pour que le code dans la condition soit exécuté.
50
PYTHON

Dans le cas où on utilise or, il suffit qu’une expression soit évaluée à True par
Python pour que le code dans la condition soit exécuté.

Ici, vous pouvez noter que Python a l’inverse de la plupart des autres langages
possède une syntaxe très logique et très intuitive qui va nous permettre
d’effectuer plusieurs tests dans une condition “comme si” on utilisait un
opérateur logique and en utilisant tout simplement plusieurs opérateurs de
comparaison à la suite.

Je vous recommande cependant plutôt d’utiliser des opérateurs logiques dans


cette situation afin de rendre votre code plus clair.

Finalement, l’opérateur logique not est très particulier puisqu’il nous permet
d’inverser la valeur logique d’un test : si Python renvoie False à l’issue d’une
évaluation par exemple et qu’on utilise l’opérateur not sur cette expression
l’opérateur inversera la valeur renvoyée par Python et la valeur finale passée à la
condition sera True.

2.2.2. Présentation des opérateurs d’appartenance ou d’adhésion


51
PYTHON

Python met à notre disposition deux opérateurs d’appartenant qui vont nous
permettre de tester si une certaine séquence de caractères ou de valeurs est
présente ou pas dans une valeur d’origine.

Ces opérateurs ne vont fonctionner qu’avec des séquences (chaines de


caractères, listes, etc.) et ne vont donc pas marcher avec des valeurs de type
numérique par exemple.

L’opérateur in permet de tester si une certaine séquence de caractères ou de


valeurs est présente dans une valeur d’origine et renvoie True si c’est le cas.

L’opérateur not in permet au contraire de tester si une certaine séquence de


caractères ou de valeurs n’est pas présente dans une valeur d’origine et renvoie
True si c’est le cas.

Comme des valeurs booléennes sont renvoyées, on va tout à fait pouvoir utiliser
ce type d’opérateurs au sein de nos conditions même si ils sont communément
plus utilisés au sein de boucles qu’on étudiera dans la prochaine leçon.

2.2.3 Un point sur l’ordre de priorité des opérateurs

Dans les exemples précédents, nous avons utilisé plusieurs opérateurs différents
dans nos conditions : des opérateurs de comparaisons divers, des opérateurs
logiques, etc.

Rien ne nous empêche à priori de rajouter des opérateurs arithmétiques et


d’utiliser plusieurs opérateurs logiques dans ces mêmes conditions.
52
PYTHON

A partir de là, cependant, il faut commencer à être très rigoureux pour obtenir
des résultats conformes à nos attentes et il va notamment falloir bien connaitre
l’ordre de priorité d’application des différents opérateurs en Python.

Ci-dessous, vous pourrez trouver l’ordre de traitement de chaque opérateur


Python (classés du plus prioritaire au moins prioritaire). Certains nous sont
encore inconnus, je vous demande de ne pas vous en préoccuper pour le
moment.

Opérateur Description

() Opérateur de groupement

** Elévation à la puissance

~ Opérateur d’inversion de bit

Opérateurs arithmétiques multiplication,


*, /, %
division et modulo

<<, >> Décalage de bits à gauche ou à droite

& Définit chaque bit à 1 si les deux bits valent 1

Définit chaque bit à 1 si seulement l’un des


^
deux bits vaut 1

Définit chaque bit à 1 si au moins l’un des


|
deux bits vaut 1

==, !=, <, <=, >, >=, in, not in, is, Opérateurs de comparaison, d’appartenance et
is not d’identité

not Opérateur logique (booléen) inverse ou “non”

and Opérateur logique (booléen) “et”

or Opérateur logique (booléen) “ou”

2.4. Les boucles Python for et while


Les boucles, tout comme les conditions, sont une structure de contrôle Python de
base et il est donc essentiel de comprendre comment elles fonctionnent et de
savoir les utiliser.
53
PYTHON

2.4.1 Présentation des boucles en Python

Les boucles vont nous permettre d’exécuter plusieurs fois un bloc de code, c’est-
à-dire d’exécuter un code « en boucle » tant qu’une condition donnée est
vérifiée.

Lorsqu’on code, on va en effet souvent devoir exécuter plusieurs fois un même


code. Utiliser une boucle nous permet de n’écrire le code qu’on doit exécuter
plusieurs fois qu’une seule fois.

Nous allons ainsi pouvoir utiliser les boucles pour parcourir les valeurs d’une
variable de liste liste ou pour afficher une suite de nombres.

Nous avons accès à deux boucles en Python :

 La boucle while (“tant que…”) ;


 La boucle for (“pour…”).

Le fonctionnement général des boucles sera toujours le même : on pose une


condition qui sera généralement liée à la valeur d’une variable et on exécute le
code de la boucle « en boucle » tant que la condition est vérifiée.

Pour éviter de rester bloqué à l’infini dans une boucle, vous pouvez donc déjà
noter qu’il faudra que la condition donnée soit fausse à un moment donné (pour
pouvoir sortir de la boucle). Selon le type de condition, on va avoir différents
moyens de faire cela. Nous allons voir les plus courants dans la suite de cette
leçon.

2.4.2 La boucle Python while

La boucle while va nous permettre d’exécuter un certain bloc de code « tant


qu’une » condition donnée est vérifiée. Sa syntaxe est la suivante :
54
PYTHON

On commence ici par créer une variable x et on stocke la valeur 0 dedans.

On crée ensuite notre boucle while qui va baser sa condition de sortie autour de
la valeur de la variable x.

Littéralement, cette boucle signifie “tant que x stocke une valeur strictement
inférieure à 10, affiche la valeur de x puis ajoute 1 à cette valeur”.

Lors du premier tour dans la boucle, x stocke la valeur 0 qui est bien inférieure à
10. On rentre donc dans la boucle, on affiche la valeur de x et on ajoute 1 à cette
valeur.

Une fois arrivés en fin de boucle, on retourne au début de la boucle. On teste à


nouveau si x contient une valeur inférieure à 10. C’est le cas puisque x stocke
désormais 1. On affiche à nouveau la valeur de x et on lui ajoute à nouveau 1.

On retourne à nouveau au début de la boucle et etc. Jusqu’à ce que la condition


de sortie soit vérifiée, c’est-à-dire jusqu’à ce que x stocke une valeur supérieure
ou égale à 10. Dans ce cas là, la boucle est ignorée et on passe à l’instruction
suivante.

Note : Lorsqu’on ajoute 1 à une variable, on dit qu’on l’incrémente. À l’inverse,


lorsqu’on enlève 1 à la valeur d’une variable, on dit qu’on la décrémente. Les
opérations d’incrémentation et de décrémentation sont très fréquentes au sein
55
PYTHON

des boucles. On s’en sert généralement pour que la condition d’exécution de la


boucle soit fausse à un moment donnée.

2.4.3 La boucle Python for

La boucle Python for possède une logique et une syntaxe différente de celles des
boucle for généralement rencontrées dans d’autres langages.

En effet, la boucle for Python va nous permettre d’itérer sur les éléments d’une
séquence (liste, chaine de caractères, etc.) selon leur ordre dans la séquence.

La condition de sortie dans cette boucle va être implicite : on sortira de la boucle


après avoir parcouru le dernier élément de la séquence.

La syntaxe de cette boucle va être la suivante :

2.4.4 La fonction range()

On va pouvoir utiliser la fonction range() pour itérer sur une suite de nombres
avec une boucle for.

Cette fonction permet de générer une suite de valeurs à partir d’une certain
nombre et jusqu’à un autre avec un certain pas ou intervalle.

Dans son utilisation la plus simple, nous allons nous contenter de passer un
nombre en argument (entre les parenthèses) de range(). Dans ce cas, la fonction
génèrera une suite de valeurs de 0 jusqu’à ce nombre – 1 avec un pas de 1.
range(5) par exemple génère les valeurs 0, 1, 2, 3 et 4.

Si on précise deux nombres en arguments de cette fonction, le premier nombre


servira de point de départ pour la génération de nombres tandis que le second
56
PYTHON

servira de point d’arrivée (en étant exclus). range(5, 10) par exemple permet de
générer les nombres 5, 6, 7, 8 et 9.

Finalement, on peut préciser un troisième et dernier nombre en argument de


range() qui nous permet de préciser son pas, c’est-à-dire l’écart entre deux
nombres générés. Ecrire range(0, 10, 2) par exemple permet de générer les
nombres 0, 2, 4, 6 et 8.

On va pouvoir utiliser la fonction range() plutôt qu’une variable de type


séquence avec nos boucles for pour itérer sur une suite de nombres.

2.4.5 Les instructions break et continue


57
PYTHON

Les instructions break et continue sont deux instructions qu’on retrouve dans de
nombreux langages et qui sont souvent utilisées avec les boucles mais qui
peuvent être utilisées dans d’autres contextes.

L’instruction break permet de stopper l’exécution d’une boucle lorsqu’une


certaine condition est vérifiée. On l’inclura souvent dans une condition de type
if.

Par exemple, on va pouvoir stopper l’exécution d’une boucle lorsqu’une


variable contient une valeur en particulier.

L’instruction continue permet elle d’ignorer l’itération actuelle de la boucle et


de passer directement à l’itération suivante. Cette instruction va donc nous
permettre d’ignorer toute ou partie de notre boucle dans certaines conditions et
donc de personnaliser le comportement de notre boucle.
58
PYTHON

CHAPITRE 3. LES FONCTIONS


PYTHON
3.1 Introduction aux fonctions Python

3.2. Notions avancées sur les paramètres des fonctions Python

3.3 Contrôle des valeurs de retour d’une fonction Python

3.4 La portée des variables en Python

Annexe 1 : Quelques fonctions Python utiles

3.1 Introduction aux fonctions Python


Dans cette nouvelle partie, nous allons étudier une autre notion incontournable
de tout langage de programmation qui se respecte : les fonctions. Nous allons
notamment définir ce qu’est une fonction et comprendre l’intérêt d’utiliser ces
structures puis nous verrons comment créer nos propres fonctions en Python
ainsi que certains concepts avancés relatifs aux fonctions.

3.1.1 Qu’est-ce qu’une fonction ?


59
PYTHON

Une fonction est un bloc de code nommé. Une fonction correspond à un


ensemble d’instructions créées pour effectuer une tâche précise, regroupées
ensemble et qu’on va pouvoir exécuter autant de fois qu’on le souhaite en
“l’appelant” avec son nom. Notez “qu’appeler” une fonction signifie exécuter
les instructions qu’elle contient.

L’intérêt principal des fonctions se situe dans le fait qu’on va pouvoir appeler
une fonction et donc exécuter les instructions qu’elle contient autant de fois
qu’on le souhaite, ce qui constitue au final un gain de temps conséquent pour le
développement d’un programme et ce qui nous permet de créer un code
beaucoup plus clair.

Il existe deux grands “types” de fonctions en Python : les fonctions prédéfinies


et les fonctions créées par l’utilisateur.

3.1.2 Les fonctions prédéfinies Python

Les fonction prédéfinies sont des fonctions déjà créées et mises à notre
disposition par Python. Dans ce cours, nous avons déjà utilisé des fonctions
prédéfinies comme la fonction print() ou la fonction type() par exemple.

Ici, je tiens à rappeler qu’en programmation rien n’est magique : la


“programmation”… ne représente que des séries d’instruction programmées.

Lorsqu’on a utilisé print() pour afficher des données pour la première fois ou
type() pour connaitre le type d’une donnée, on ne s’est pas posé la question de
ce qu’il se passait en arrière plan.

En fait, ces deux fonctions sont des fonctions complexes et qui contiennent de
nombreuses lignes d’instructions leur permettant d’accomplir une tâche précise :
l’affichage d’un résultat ou la détermination du type d’une valeur en
l’occurence.

Cette complexité nous est cachée : nous n’avons qu’à appeler nos fonctions pour
qu’elles fassent leur travail et n’avons pas à écrire la série d’instructions qu’elles
contiennent à chaque fois et c’est tout l’intérêt des fonctions.

Python, dans sa version 3.7.4, met à notre disposition quasiment 70 fonctions


prédéfinies (sans compter les fonctions des modules ou extensions dont nous
parlerons plus tard). Vous pouvez déjà trouver la liste ci-dessous. Nous serons
amenés à utiliser la plupart d’entre elles dans ce cours ; nous les définirons à ce
moment là. Considérez le tableau ci-dessous comme une simple référence.
60
PYTHON

Liste des fonction prédéfinies Python 3.7.4

memoryview
abs() delattr() hash() set()
()

all() dict() help() min() setattr()

any() dir() hex() next() slice()

ascii() divmod() id() object() sorted()

enumerate( staticmethod(
bin() input() oct()
) )

bool() eval() int() open() str()

isinstance(
breakpoint() exec() ord() sum()
)

issubclass(
bytearray() filter() pow() super()
)

bytes() float() iter() print() tuple()

callable() format() len() property() type()

chr() frozenset() list() range() vars()

classmethod(
getattr() locals() repr() zip()
)

compile() globals() map() reversed() __import()__

complex() hasattr() max() round()

3.1.3 Les fonction Python définies par l’utilisateur

En plus des fonction prédéfinies, Python nous laisse la possibilité de définir nos
propres fonctions. Ces fonctions ne seront bien évidemment disponibles et
utilisables que dans l’espace où elles ont été définies, c’est-à-dire uniquement au
sein de nos scripts et non pas pour l’ensemble des développeurs utilisant Python.
61
PYTHON

On va vouloir créer nos propres fonctions Python lorsque nos programmes


utilisent de manière répétées une même série d’instructions : plutôt que de
réécrire ces instructions à chaque fois, autant utiliser une fonction !

Les fonctions vont aussi être de très bons outils d’abstraction lorsqu’on voudra
distribuer notre code : on préférera souvent fournir des fonctions à utiliser aux
autres développeurs plutôt que de les laisser se débrouiller avec des séries
d’instructions “sauvages”.

Pour définir une nouvelle fonction en Python, nous allons utiliser le mot clef def
qui sert à introduire une définition de fonction. Ce mot clef doit être suivi du
nom de la fonction, d’une paire de parenthèses au sein desquelles on pourra
fournir une liste de paramètres (nous reviendrons là dessus plus tard) et de : pour
terminer la ligne comme ceci def ma_fonction():.

Le nom d’une fonction Python doit respecter les normes usuelles concernant les
noms : un nom de fonction doit commencer par une lettre ou un underscore et ne
contenir que des caractères alphanumériques classiques (pas d’accent ni de
cédille ni aucun caractère spécial).

Notez que les noms de fonctions sont sensibles à la casse en Python, ce qui
signifie que les fonctions ma_fonction(), Ma_fonction(), ma_FONCtion() et
MA_FONCTION() par exemple seront des fonctions bien différentes pour
Python.

Nous allons ensuite placer la liste des différentes instructions de notre fonction à
la ligne suivant sa définition et en les indentant par rapport à la définition afin
que Python comprenne que ces instructions appartiennent à notre fonction.
Notez que la première instruction d’une fonction peut être une chaîne de
caractères littérale qui sera alors utilisée comme chaine de documentation de la
fonction.

Créons immédiatement deux fonctions bonjour() et BONJOUR() toutes simples


dont le but va être d’afficher un message en exécutant elles-mêmes une fonction
print(). On va faire cela comme cela :
62
PYTHON

Nous avons ici défini nos deux premières fonctions. Ces fonctions ne sont pas
très utiles ici : elles se contentent simplement d’exécuter une fonction print()
mais c’est déjà un bon début !

Maintenant que nos fonctions sont créées, nous allons devoir les appeler pour
exécuter le code qu’elles contiennent. Pour cela, nous allons utiliser leur nom
suivi d’un couple de parenthèses. On va pouvoir appeler nos fonctions autant de
fois qu’on le souhaite dans notre script : c’est tout l’intérêt des fonctions !

3.1.4 Les paramètres et arguments des fonctions

Les fonctions que nous avons créées ci-dessus se contentent d’exécuter toujours
la même fonction print() et donc de renvoyer toujours le même message.

Elles ne sont pas très utiles en l’état. Un autre aspect fondamental des fonctions
est qu’elles vont pouvoir accepter des informations qui viennent de l’extérieur,
c’est-à-dire qui sont externes à leur définition et qui vont les amener à produire
des résultats différents. Souvent même, les fonctions vont avoir besoin qu’on
leur passe des informations externes pour fonctionner normalement.

C’est par exemple le cas des fonctions print() et type() : ces deux fonctions
permettent d’afficher un message et de déterminer le type d’une donnée. Pour
afficher un message, print() va avoir besoin qu’on lui passe les données qu’elle
doit afficher. De même, type() va avoir besoin qu’on lui fournisse la donnée
dont elle doit déterminer le type.
63
PYTHON

Ces informations dont vont avoir besoin certaines fonctions pour fonctionner et
qu’on va passer à nos fonctions entre le couple de parenthèses sont appelées des
arguments ou des paramètres.

Pour rester très simple et très schématique ici, on parle de “paramètres”


lorsqu’on définit une fonction, c’est-à-dire lorsqu’on indique dans la définition
de la fonction que telle fonction a besoin d’une, de deux… informations pour
fonctionner et on parle “d’arguments” pour désigner les valeurs effectivement
passées à une fonction lorsqu’on l’utilise.

Illustrons cela immédiatement en reprenant et en modifiant notre fonction


bonjour() afin qu’elle affiche “Bonjour “ suivi du nom de quelqu’un qui va lui
être fourni ultérieurement. Pour réaliser cela, on va indiquer dans la définition de
la fonction que celle-ci a besoin d’un paramètre pour fonctionner.

On peut donner n’importe quel nom à ce paramètre dans la définition puisque


celui-ci sera dans tous les cas remplacé par la valeur effective passée lors de
l’appel à la fonction. Pour une meilleure lisibilité, il est cependant conseillé de
fournir des noms descriptifs et paramètres des fonctions. On peut par exemple
l’appeler prenom dans notre cas :

Expliquons ce code. On crée une nouvelle fonction bonjour() dont le rôle est
d’afficher “Bonjour” suivi du prénom de quelqu’un. Pour que cela fonctionne, il
va falloir lui passer un prénom lorsqu’on appelle notre fonction en argument de
celle-ci.

Dans la définition de la fonction, on va donc indiquer que notre fonction a


besoin d’un paramètre pour fonctionner. Ici, on choisit le mot “prenom” pour
définir notre paramètre. On aurait aussi bien pu choisir “toto”. Ensuite, dans le
corps de notre fonction, on utilise une fonction print() qui va afficher “Bonjour”
suivi du prénom qu’on aura indiqué lorsqu’on utilisera la fonction.
64
PYTHON

Ici, je vous rappelle que le mot qu’on utilise comme paramètre lors de la
définition de la fonction sera remplacé par la valeur passée en argument lors de
l’appel à la fonction. On va donc utiliser notre paramètre dans print() afin que
cette fonction affiche bien “Bonjour” suivi d’un prénom.

On utilise ensuite notre fonction plusieurs fois, en lui passant un prénom


différent à chaque fois en argument. La valeur passée va se substituer au
paramètre défini lors de la définition de la fonction.

Le code de notre fonction n’est cependant pas très optimisé ici : en effet, on
utilise de la concaténation dans print() or la concaténation ne va fonctionner que
si la valeur passée est bien une chaine de caractères. Si on passe un un chiffre en
argument de bonjour(), Python renverra une erreur.

Ici, il va être plus efficace de passer le texte et l’argument comme deux


arguments différents de print(). En effet, vous devez savoir que print() est
capable d’accepter un nombre infini d’arguments qu’elle affichera à la suite.
Cela résout notre problème de type de valeurs :

3.2 Notions avancées sur les paramètres des fonctions Python


Dans cette leçon, nous allons étudier quelques concepts relativement avancés
liés au nombre de paramètres des fonctions en passant en revue différentes
syntaxes qui vont nous permettre de passer un nombre variable d’arguments à
une fonction.

3.2.1 Créer des fonctions acceptant un nombre variable d’arguments

Dans la leçon précédente, nous avons défini ce qu’étaient des paramètres et des
arguments. Nous avons créé une fonction bonjour() qui avait besoin qu’on lui
passe un argument pour fonctionner comme ceci :
65
PYTHON

Cette définition impose qu’on passe un et un seul argument à notre fonction


pour qu’elle fonctionne : si on tente de l’appeler sans argument ou en lui passant
plusieurs arguments Python renverra une erreur.

Dans certaines situations, nous voudrons créer des fonctions plus flexibles qui
pourront accepter un nombre variable d’arguments. Cela peut être utile si on
souhaite créer une fonction de calcul de somme par exemple qui devra
additionner les différents arguments passés sans limite sur le nombre
d’arguments et sans qu’on sache à priori combien de valeurs vont être
additionnées.

En Python, il existe deux façons différentes de créer des fonctions qui acceptent
un nombre variable d’arguments. On peut :

 Définir des valeurs de paramètres par défaut lors de la définition d’une


fonction ;
 Utiliser une syntaxe particulière permettant de passer un nombre arbitraire
d’arguments.

3.2.2 Préciser des valeurs par défaut pour les paramètres d’une fonction

On va déjà pouvoir préciser des valeurs par défaut pour nos paramètres. Comme
leur nom l’indique, ces valeurs seront utilisées par défaut lors d’un appel à la
fonction si aucune valeur effective (si aucun argument) n’est passée à la place.

Utiliser des valeurs par défaut pour les paramètres de fonctions permet donc aux
utilisateurs d’appeler cette fonction en passant en omettant de passer les
arguments relatifs aux paramètres possédant des valeurs par défaut.

On va pouvoir définir des fonctions avec des paramètres sans valeur et des
paramètres avec des valeurs par défaut. Attention cependant : vous devez bien
comprendre qu’ici, si on omet de passer des valeurs lors de l’appel à la fonction,
Python n’a aucun moyen de savoir quel argument est manquant. Si 1, 2, etc.
arguments sont passés, ils correspondront de facto au premier, aux premier et
deuxième, etc. paramètres de la définition de fonction.
66
PYTHON

Pour cette raison, on placera toujours les paramètres sans valeur par défaut au
début et ceux avec valeurs par défaut à la fin afin que le arguments passés
remplacent en priorité les paramètres sans valeur.

Si on souhaite s’assurer que les valeurs passées à une fonction vont bien
correspondre à tel ou tel paramètre, on peut passer à nos fonctions des
arguments nommés. Un argument nommé est un argument qui contient le nom
d’un paramètre présent dans la définition de la fonction suivi de la valeur qu’on
souhaite passer comme ceci : argument = valeur.

On va pouvoir passer les arguments nommés dans n’importe quel ordre puisque
Python pourra faire le lien grâce au nom avec les arguments attendus par notre
fonction. Notez cependant qu’il faudra ici passer les arguments nommés en
dernier, après les arguments sans nom. Par ailleurs, aucun argument ne peut
recevoir de valeur plus d’une fois. Faites donc bien attention à ne pas passer une
valeur à un argument sans le nommer puis à repasser cette valeur en le nommant
par inattention.
67
PYTHON

3.2.3 Passer un nombre arbitraire d’arguments avec *args et **kwargs

La syntaxe *args (remplacez “args” par ce que vous voulez) permet d’indiquer
lors de la définition d’une fonction que notre fonction peut accepter un nombre
variable d’arguments. Ces arguments sont intégrés dans un tuple. On va pouvoir
préciser 0, 1 ou plusieurs paramètres classiques dans la définition de la fonction
avant la partie variable.
68
PYTHON

Ici, on utilise une boucle for pour itérer parmi les arguments : tant que des
valeurs sont trouvées, elles sont ajoutées à la valeur de s. Dès qu’on arrive à
court d’arguments, on print() le résultat.

De façon alternative, la syntaxe **kwargs (remplacez “kwargs” par ce que vous


voulez) permet également d’indiquer que notre fonction peut recevoir un
nombre variable d’arguments mais cette fois-ci les arguments devront être
passés sous la forme d’un dictionnaire Python.

Dans cette exemple, j’utilise la méthode Python items() dont le rôle est de
récupérer les différentes paires clefs : valeurs d’un dictionnaire. Nous
reparlerons des méthodes lorsque nous aborderons l’orienté objet. Pour le
moment, vous pouvez considérer qu’une méthode est l’équivalent d’une
fonction.

3.2.4 Séparer des données pour les passer à une fonction

Les syntaxes *args et **kwargs peuvent être utilisées pour réaliser les
opérations inverse de celles présentés ci-dessus, à savoir séparer des données
composites pour passer les valeurs ou éléments de ces données un à un en
arguments des fonctions.

On, utilisera la syntaxe *args pour séparer les arguments présents dans une liste
ou un tuple et la syntaxe **kwargs pour séparer les arguments présents dans un
dictionnaire et fournir des arguments nommés à une fonction.
69
PYTHON

3.3 Contrôle des valeurs de retour d’une fonction Python


Dans cette leçon, nous allons voir comment faire pour que nos fonctions
retournent explicitement une valeur et comprendre l’intérêt de faire retourner
une valeur à nos fonctions Python.

3.3.1 Présentation de l’instruction return et cas d’utilisation

Jusqu’à présent, nos fonctions n’ont fait qu’afficher leur résultat après qu’on les
ait appelées. En pratique, cette façon de procéder est rarement utilisée et ceci
pour deux raisons : d’une part, nous n’avons aucun contrôle sur le résultat
affiché puisque celui est affiché dès que la fonction a fini de s’exécuter et
ensuite car nous ne pouvons pas utiliser ce résultat pour effectuer de nouvelles
opérations.

Or, en programmation, nous voudrons souvent récupérer le résultat d’une


fonction afin de l’utiliser dans le reste de notre script. Pour cela, il va falloir
qu’on demande à notre fonction de retourner (renvoyer) le résultat de ses
opérations. Nous allons pouvoir faire cela en Python grâce à l’instruction return.

Attention cependant : l’instruction return va terminer l’exécution d’une fonction,


ce qui signifie qu’on placera généralement cette instruction en fin de fonction
puisque le code suivant une instruction return dans une fonction ne sera jamais
lu ni exécuté.

3.3.2 Premier exemple d’utilisation de return en Python

Imaginons que nous soyons en train de créer un programme relativement


complexe qui effectue des séries de calculs intermédiaires pour finalement
arriver à un résultat final.

Notre programme va être composé de différentes fonctions qui vont se charger


d’effectuer ces différents calculs à la suite les unes des autres. Certaines
fonctions vont fonctionner différemment ou même ne pas s’exécuter du tout en
70
PYTHON

fonction du résultat renvoyé par la fonction précédente dans la chaine de


fonctions.

Ce type de situations est très fréquent en programmation : on exécute une


première fonction qui renvoie un résultat et on injecte ce résultat dans la
fonction suivante et etc. On va pouvoir faire cela avec une instruction return.

Pour cela, créons par exemple une fonction très simple qui renvoie la différence
entre deux nombres.

Ici, on utilise return afin de demander à notre fonction de retourner son résultat.
On stocke ensuite ce résultat dans une variable x dont on pourra se resservir
dans la suite du script.

3.3.3 Utiliser return pour retourner plusieurs valeurs

Une fonction ne peut retourner qu’une donnée à la fois. Cependant, Python met
à notre disposition des types de données composites comme les listes ou les
tuples par exemple.

On va donc pouvoir utiliser return pour faire retourner “plusieurs valeurs” à la


fois à nos fonctions ou pour être tout à fait exact pour leur faire retourner une
donnée composite.

Pour cela, on va préciser les différentes valeurs que doit retourner return en les
séparant par des virgules. Les valeurs retournées seront retournées dans un tuple.
71
PYTHON

3.3.4 Les fonctions récursives

Nous avons vu dans les leçon précédente qu’une fonction pouvait exécuter une
autre fonction, par exemple dans le cas où on demande à une fonction d’exécuter
une fonction print() pour afficher une valeur.

Vous devez savoir qu’une fonction peut également s’appeler elle même dans son
exécution : c’est ce qu’on appelle la récursivité. Lorsqu’on définit une fonction
récursive, il faudra toujours faire bien attention à fournir une condition qui sera
fausse à un moment ou l’autre au risque que la fonction s’appelle à l’infini.

L’exemple de fonction récursive par excellence est la définition d’une fonction


qui calculerait une factorielle. La factorielle d’un nombre est le produit des
nombres entiers inférieurs ou égaux à celui-ci; la factorielle de 4 par exemple est
égale à 4 * 3 * 2 * 1.

Créons immédiatement cette fonction :


72
PYTHON

Ici, la condition de sortie de notre fonction est atteinte dès que la valeur passée
en argument atteint ou est inférieure à 1. Expliquons comment fonctionne cette
fonction en détail. Si on passe une valeur inférieure ou égale à 1 à notre fonction
au départ, on retourne la valeur 1 et la fonction s’arrête.

Si on passe une valeur strictement supérieure à 1, on retourne cette valeur et on


appelle factorielle(n-1). Si n-1 représente toujours une valeur strictement
supérieure à 1, on retourne cette valeur et on appelle à nouveau notre fonction
avec une valeur diminuée de 1 et etc. Jusqu’à ce que la valeur passée à
factorielle() atteigne 1.

3.3.5 Un peu de vocabulaire : fonction vs procédure en Python

Par définition, toute fonction est censée renvoyer une valeur. Une fonction qui
ne renvoie pas de valeur n’est pas une fonction : on appelle cela en
programmation une procédure.

En Python, en fait, même les fonctions sans instruction return explicite renvoient
une valeur qui est None. Le valeur None est une valeur qui correspond justement
à l’absence de valeur. Cette valeur sert à indiquer “il n’y a pas de valeur”.

L’interpréteur Python l’ignore lorsque c’est la seule valeur qui est renvoyée
mais elle existe tout de même et c’est la raison pour laquelle on appelle les
fonctions qui ne possèdent pas de return explicite des fonctions en Python.

3.4 La portée des variables en Python


Dans cette leçon, nous allons découvrir un concept fondamental lié aux
fonctions et aux variables qui est celui de portée des variables. Nous allons
comprendre les conditions d’accès et d’utilisation des différentes variables dans
un script.

3.4.1 Définition de la portée des variables en Python


73
PYTHON

En Python, nous pouvons déclarer des variables n’importe où dans notre script :
au début du script, à l’intérieur de boucles, au sein de nos fonctions, etc.

L’endroit où on définit une variable dans le script va déterminer l’endroit où la


variable va être accessible c’est-à-dire utilisable.

Le terme de “portée des variables” sert à désigner les différents espaces dans le
script dans lesquels une variable est accessible c’est-à-dire utilisable. En Python,
une variable peut avoir une portée locale ou une portée globale.

3.4.2 Variables globales et variables locales en Python

Les variables définies dans une fonction sont appelées variables locales. Elles ne
peuvent être utilisées que localement c’est-à-dire qu’à l’intérieur de la fonction
qui les a définies. Tenter d’appeler une variable locale depuis l’extérieur de la
fonction qui l’a définie provoquera une erreur.

Cela est dû au fait que chaque fois qu’une fonction est appelée, Python réserve
pour elle (dans la mémoire de l’ordinateur) un nouvel espace de noms (c’est-à-
dire une sorte de dossier virtuel). Les contenus des variables locales sont stockés
dans cet espace de noms qui est inaccessible depuis l’extérieur de la fonction.

Cet espace de noms est automatiquement détruit dès que la fonction a terminé
son travail, ce qui fait que les valeurs des variables sont réinitialisées à chaque
nouvel appel de fonction.

Les variables définies dans l’espace global du script, c’est-à-dire en dehors de


toute fonction sont appelées des variables globales. Ces variables sont
74
PYTHON

accessibles (= utilisables) à travers l’ensemble du script et accessible en lecture


seulement à l’intérieur des fonctions utilisées dans ce script.

Pour le dire très simplement : une fonction va pouvoir utiliser la valeur d’une
variable définie globalement mais ne va pas pouvoir modifier sa valeur c’est-à-
dire la redéfinir. En effet, toute variable définie dans une fonction est par
définition locale ce qui fait que si on essaie de redéfinir une variable globale à
l’intérieur d’une fonction on ne fera que créer une autre variable de même nom
que la variable globale qu’on souhaite redéfinir mais qui sera locale et bien
distincte de cette dernière.

3.4.3 Modifier une variable globale depuis une fonction

Dans certaines situations, il serait utile de pouvoir modifier la valeur d’une


variable globale depuis une fonction, notamment dans le cas où une fonction se
sert d’une variable globale et la manipule.

Cela est possible en Python. Pour faire cela, il suffit d’utiliser le mot clef global
devant le nom d’une variable globale utilisée localement afin d’indiquer à
Python qu’on souhaite bien modifier le contenu de la variable globale et non pas
créer une variable locale de même nom.
75
PYTHON

Annexe 1 : Quelques fonctions Python utiles


Nous connaissons déjà bien les fonction print() et type() qui permettent
respectivement d’afficher des données ou de connaitre le type d’une donnée
Python.

Python ne contient pas énormément de fonctions prédéfinies -seulement celles


qui s’avèrent le plus utiles- et la plupart d’entre elles sont donc très
régulièrement utilisées.

Vous trouverez dans la suite de cette leçon quelques définitions de fonctions qui
pourront vous servir par la suite.

Les fonctions de conversion

Python possède certaines fonctions qui nous permettent de modifier le type de


certaines données, c’est-à-dire de les “convertir”. Ces fonctions portent le nom
du type de donnée souhaitée :

 La fonction str() retourne une chaine de caractères à partir d’une donnée


qu’on va lui passer en argument ;
 La fonction int() retourne un entier à partir d’un nombre ou d’une chaine
contenant un nombre qu’on va lui passer en argument ;
 La fonction float() retourne un nombre décimal à partir d’un nombre ou
d’une chaine contenant un nombre qu’on va lui passer en argument ;
 La fonction complex() retourne un nombre complexe à partir d’un nombre
ou d’une chaine contenant un nombre qu’on va lui passer en argument ;
 La fonction bool() retourne un booléen à partir d’une donnée qu’on va lui
passer en argument ;
 La fonction list() retourne une liste à partir d’une donnée itérable (une
donnée dont on peut parcourir les valeurs) ;
 La fonction tuple() retourne un tuple à partir d’une donnée itérable ;
76
PYTHON

 La fonction dict() crée un dictionnaire à partir d’un ensemble de paires


clef = “valeur” ;
 La fonction set() retourne un ensemble (set) à partir d’une donnée itérable.

Les fonctions mathématiques

Python possède également certaines fonctions qui vont nous permettre


d’effectuer des opérations mathématiques intéressantes, comme des calculs de
somme ou de recherches du plus grand ou du plus petit nombre dans une liste.

Nous allons ici étudier les fonctions range(), round(), sum(), min() et max().

La fonction range() renvoie une séquence de nombres. On peut lui passer


jusqu’à 3 arguments mais 1 seul est obligatoire.

Si on ne passe qu’un argument à range(), cette fonction va renvoyer une


séquence de nombres commençant par 0 et en incrémentant de 1 à chaque fois
jusqu’au nombre spécifié en argument moins 1.
77
PYTHON

En lui passant 2 arguments, le premier argument servira de départ pour la


séquence et le deuxième indiquera la fin de la séquence (avec le nombre indiqué
exclu).

En lui passant trois arguments, le premier argument servira de départ pour la


séquence, le deuxième indiquera la fin de la séquence (avec le nombre indiqué
exclu) et le troisième indiquera le “pas”, c’est-à-dire l’écart entre chaque nombre
renvoyé.

La fonction round() permet d’arrondir un nombre spécifié en argument t à


l’entier le plus proche avec un degré de précision (un nombre de décimales)
éventuellement spécifié en deuxième argument.

Le nombre de décimales par défaut est 0, ce qui signifie que la fonction


retournera l’entier le plus proche.

La fonction sum() permet de calculer une somme. On peut lui passer une liste de
nombres en arguments par exemple. On peut également lui passer une valeur
“de départ” en deuxième argument qui sera ajoutée à la somme calculée.

La fonction max() retourne la plus grande valeur d’une donnée itérable, c’est-à-
dire d’une donnée dont on peut parcourir les différentes valeurs.

On peut lui passer autant d’arguments qu’on souhaite comparer de valeurs.


Notez qu’on peut également comparer des chaines même si max() est peu
souvent utilisée pour faire cela.

La fonction min(), au contraire, retourne la plus petite valeur d’une donnée


itérable. Elle s’utilise exactement comme max().
78
PYTHON
79
PYTHON

Autres fonctions Python natives utiles

Parmi les autres fonctions Python prédéfinies, j’aimerais vous en présenter


rapidement quelques unes qu’on va réutiliser dans la suite de ce cours.

La fonction len(), tout d’abord, renvoie la longueur ou le nombre de valeurs


d’une donnée de type séquence ou collection.

La fonction input() permet de dialoguer et d’échanger des données avec


l’utilisateur. On va pouvoir passer un message en argument de cette fonction.
Attention : il est de votre responsabilité de bien vérifier si les données envoyées
sont conformes à celles attendues pas la suite.

La fonction dir(), lorsqu’elle est utilisée sans argument, renvoie la liste des
variables et des fonctions (ou plus exactement des objets et des méthodes)
disponibles dans l’espace de portée courant. Nous étudierons ce que sont les
objets et méthodes par la suite.

Si on lui passe une donnée en argument, elle renverra la liste des méthodes
disponibles pour ce type de donnée.
80
PYTHON
81
PYTHON

CHAPITRE 4. PYTHON ORIENTÉ


OBJET
4.1 Introduction à l’orienté objet en Python

4.2 Classes, objets et attributs en Python orienté objet

4.3 Héritage et polymorphisme en Python orienté objet

4.4 Gérer la visibilité des membres de classe en Python orienté objet

4.5 Itérateurs et générateurs en Python orienté objet

Annexe 2 : Quelques méthodes Python utiles

4.1 Introduction à l’orienté objet en Python


La programmation orientée objet (POO) est un passage obligé lors de
l’apprentissage de nombreux langage informatiques et est également un sujet
relativement ardu lorsqu’on nous le présente pour la première fois.

Cette première leçon a pour objectif de définir le plus simplement et le plus


clairement les concepts d’objets, de classes et d’attributs et de démystifier le
sujet de l’orienté objet.

Il est possible que vous ne compreniez pas tout d’un coup : pas d’inquiétude,
suivez le cours à votre rythme, avec moi, et les choses deviendront de plus en
plus claires au fil de votre avancement de le cours. N’hésitez pas à relire cette
partie en entier une fois que vous l’avez terminée pour revoir tous ces concepts
sous un oeil nouveau.

4.1.1 Qu’est-ce que la programmation orientée objet ?

La programmation orientée objet (ou POO en abrégé) correspond à une autre


manière d’imaginer, de construire et d’organiser son code.

La programmation orientée objet repose sur le concept d’objets qui sont des
entités qui vont pouvoir posséder un ensemble de variables et de fonctions qui
leur sont propres.

Les objectifs principaux de la programmation orientée objet sont de nous


permettre de créer des scripts plus clairs, mieux structurés, plus modulables et
plus faciles à maintenir et à déboguer. Nous allons illustrer cela en pratique au
cours de cette partie.
82
PYTHON

4.1.2 Le Python, un langage orienté objet

Python est un langage résolument orienté objet, ce qui signifie que le langage
tout entier est construit autour de la notion d’objets.

En fait, quasiment tout en Python est avant tout un objet et nous avons manipulé
des objets depuis le début de ce cours sans nous en rendre compte : les types str,
int, list, etc. sont avant tout des objets, les fonctions sont des objets, etc.

Pour véritablement maitriser Python et utiliser toutes ses fonctionnalités, il est


donc indispensable de comprendre cette composante orienté objet.

4.1.3 Qu’est-ce qu’un objet en programmation ?

Dans la vie réelle, un objet possède des caractéristiques et nous permet de


réaliser des actions. Un crayon par exemple possède une taille, une couleur, une
forme, etc. qui sont ses caractéristiques et permet d’écrire ou de dessiner.

Le concept d’objets en informatique s’inspire fortement de cette définition de la


vie réelle : on va appeler “objet” un bloc cohérent de code qui possède ses
propres variables (qui sont l’équivalent des caractéristiques des objets de tous
les jours) et fonctions (qui sont nos actions). Comme les objets de la vie
courante, les objets informatiques peuvent être très simples ou très complexes.

Vous pouvez déjà noter que Python parle “d’attributs” pour désigner les
variables et fonctions d’un objet et plus précisément “d’attributs de données”
pour désigner les variables d’un objet et de “méthodes” pour désigner les
fonctions qui lui sont propres.

Dans la plupart des langages informatiques, on parle plutôt de “membres” pour


désigner les variables et fonctions d’un objet et de “propriété” pour désigner les
variables et de “méthodes” pour désigner les fonctions.

4.1.4 Comment crée-t-on un objet ? Présentation des classes

En POO, un objet ne peut pas être créé ex nihiliste (à partir de rien). La plupart
des langages qui supportent l’orienté objet (dont le Python) utilisent d’autres
entités pour créer des objets qu’on appelle des classes.

Une classe est également un ensemble cohérent de code qui contient


généralement à la fois des variables et des fonctions et qui va nous servir de plan
pour créer des objets possédant un même ensemble de d’attributs de données et
de méthodes de base.
83
PYTHON

En fait, on peut aller jusqu’à considérer que les classes sont les principaux outils
de la POO puisqu’elles permettent de mettre en place des concepts
fondamentaux de la POO comme l’héritage, l’encapsulation ou le
polymorphisme qui sont des concepts qu’on expliquera et qu’on étudiera en
détail plus tard.

Pour le moment, contentez vous de retenir qu’une classe va servir de plan de


création pour un type d’objets. Créer une nouvelle classe en Python correspond
à définir un nouveau type d’objets ou un nouveau type de données.

Pour créer des objets à partir d’une classe en Python, on va utiliser cette classe
comme une fonction. Pour illustrer concrètement comment cela fonctionne et
pour que vous compreniez plus facilement, créons immédiatement une première
classe qu’on va appeler Utilisateur.

4.1.5 Création d’une première classe et d’objets Python

Pour créer une nouvelle classe Python on utilise le mot clef class suivi du nom
de notre classe. Ici, on va créer une classe Utilisateur qui va être très simple pour
le moment.

Je vous accorde que ce code peut faire peut à priori car il contient de
nombreuses nouvelles choses. Pas d’inquiétude, nous allons l’expliquer au fur et
à mesure.

Ici, on crée une nouvelle classe Utilisateur avec la syntaxe class Utilisateur:.
Notez que par convention le nom d’une classe commence toujours par une
majuscule.

Cette classe Utilisateur possède ici deux variables statut et age et définit
également une fonction setNom(). Le rôle de la fonction setNom() va être de
permettre par la suite à nos objets de type Utilisateur() de définir un attribut de
donnée nom avec une valeur qui va être propre à chacun. Je vous demande de ne
pas vous préoccuper de l’argument self le moment.
84
PYTHON

Pour créer des objets à partir de cette classe, nous allons utiliser la syntaxe
Utilisateur() comme ceci :

Lorsqu’on crée un objet à partir d’une classe comme ceci, on dit également
qu’on instancie une classe (on crée une nouvelle instance d’une classe). Ici, on
instancie deux fois notre classe et on place le résultat dans deux variables pierre
et mathilde qui deviennent automatiquement des objets de type Utilisateur.

La chose que vous devez absolument comprendre ici est que les objets créés à
partir d’une classe en Python vont automatiquement avoir accès aux variables et
fonctions définies dans la classe qui vont être pour eux des attributs de données
et des méthodes.

Nos objets pierre et mathilde disposent donc ici tous les deux de deux attributs
de données statut et age qui possèdent les valeurs Inscrit et 0 et ont également
accès à la méthode setNom().

Pour accéder aux attributs de données et aux méthodes d’un objet, il va falloir
mentionner l’objet suivi de l’opérateur . (point) suivi du nom de l’attribut de
donnée ou de la méthode à laquelle on souhaite accéder comme ceci :
85
PYTHON

Ce n’est pas tout : nos objets vont également pouvoir définir des valeurs
personnalisées pour leurs attributs de données et on va également pouvoir
définir de nouveaux attributs de données qui vont être propres à un objet en
particulier dans une classe :

4.1.6 Conclusion sur cette introduction à l’orienté objet Python

Nous venons de faire une première (grosse) introduction à la programmation


orientée objet et avons dans cette leçon défini et découvert de nombreuses
nouvelles entités comme les objets, les classes, etc. et de nouveaux concepts
comme l’encapsulation, l’héritage, etc.
86
PYTHON

Si vous ne comprenez pas tout pour le moment et si vous êtes un peu perdu,
aucune inquiétude : c’est tout à fait normal. Considérez qu’entamer la POO est
un petit peu comme si vous commenciez ce cours.

Plus vous allez avancer dans cette partie, plus les différents éléments vont faire
sens et mieux vous comprendrez chaque chose car la plupart des concepts
présentés ici ont besoin que vous connaissiez d’autres concepts pour être
compris mais pour vous présenter ces autres concepts j’ai besoin de vous
présenter avant les premier concepts bref… C’est l’histoire du serpent qui se
mord la queue ou de l’oeuf et la poule : il faut choisir un angle d’attaque pour
expliquer la suite et progresser.

Pour le moment, je vous conseille de ne pas trop vous formaliser sur cette
nouvelle syntaxe ni sur les nouveaux termes. Essayez simplement de retenir ces
deux points pour la suite :

 Les classes sont des ensembles de code qui contiennent des variables et
des fonctions et qui vont nous servir à créer des objets ;
 Les objets créés à partir d’une classe disposent automatiquement des
variables et des fonctions définies dans la classe.

4.2 Classes, objets et attributs en Python orienté objet


L’objectif de cette leçon est de clarifier certains des concepts vus dans la leçon
précédente et de comprendre comment utiliser nos classes et nos objets en
détail.

4.2.1 Différence entre variable et attribut de données et entre fonction et


méthode

Les classes permettent de réunir des données et des fonctionnalités. Ici, vous
devez bien comprendre qu’une classe n’est finalement qu’un objet qui permet de
créer d’autres objets de même type. Comme cet objet est différent des autres, on
appelle cela une “classe” mais ce n’est que du vocabulaire.

Créer une nouvelle classe en Python revient à créer un nouveau type d’objet et
de fait un nouveau type de données. On va ensuite pouvoir instance notre classe
pour créer des objets qui vont partager les variables et fonctions de leur classe.

Pour désigner les variables et les fonctions que les objets héritent de leur classe,
Python utilise les termes “attributs de données” et “méthodes”.
87
PYTHON

Les termes employés sont différents (et le sont dans tous les langages qui
supportent l’orienté objet) car ils servent à désigner des éléments de langage
différents.

L’idée principale à retenir ici est qu’un attribut de donnée ou une méthode est
propre à un objet tandis qu’une variable ou une fonction est indépendante de
tout objet. C’est la raison pour laquelle pour accéder à un attribut de données ou
à une méthode on doit préciser le nom de l’objet qui souhaite y accéder avant.

Si on tente d’accéder à un attribut de donnée ou à une méthode définis dans une


classe sans objet ou à partir d’un objet d’une autre classe, Python renverra une
erreur puisqu’encore une fois les attributs de données de classe et les méthodes
de classes sont propres et ne sont partagés que par les objets de la classe. C’est
le principe “d’encapsulation” que nous allons expliquer en détail juste après.

En plus de cela, notez qu’un objet peut également définir ses propres attributs de
données ou surcharger des attributs de données de classe.

4.2.2 Les classes et le principe d’encapsulation

L’un des grands intérêts des classes est qu’elles permettent l’encapsulation du
code, c’est-à-dire le fait d’enfermer le code dans une “capsule”, dans un espace
en dehors de l’espace global. Cela permet d’éviter d’utiliser des variables
globales et de polluer l’espace global du script.

En effet, dans tous les langages de programmation, il est considéré comme une
bonne pratique de limiter le recours aux variables globales car cela rend le code
non flexible, non modulable, et dur à entretenir.

Pour comprendre cela, il faut penser au fait que la plupart des programmes
aujourd’hui contiennent des dizaines de fichiers qui contiennent chacun des
centaines de lignes de code et qui font appel à de nombreux modules externes,
c’est-à-dire à des code préconçus fournis par d’autres personnes.

Dans ces conditions, on ne peut pas se permettre de déclarer ses variables ou


fonction n’importe comment car les risques de conflits, c’est-à-dire les risques
qu’un même nom de variable ou de fonction soit utilisé plusieurs fois pour
définir plusieurs variables ou fonctions entre fichiers et modules sont grands.

Pour cette raison, un bon développeur fera tout pour compartimenter son code
en créant des espaces de portée ou “espaces de noms” bien définis et dont les
éléments ne pourront pas entrer en conflit avec les autres.
88
PYTHON

Les classes nous permettent de mettre en place cela puisque chaque objet créé à
partir d’une classe sa posséder SES attributs de données et SES méthodes qui ne
vont pas être accessibles depuis l’extérieur de l’objet et qui ne vont donc pas
polluer l’espace global.

4.2.3 Initialiser des objets avec __init__()

Dans la leçon précédente, nous avons défini une première classe Utilisateur() et
avons créé deux objets pierre et mathilde à partir de cette classe comme cela :

Ici, lors de leur création, les deux objets pierre et mathilde disposent des mêmes
attributs avec les mêmes valeurs telles que définies dans la classe.

Ce type de comportement est, en pratique, rarement voulu. Généralement, on


voudra que les objets disposent déjà d’attributs avec des valeurs qui leur sont
propres dès leur création.

Pour réaliser cela, nous allons modifier notre classe et lui ajouter une fonction
spéciale appelée __init__() (deux underscores avant et deux après le nom) qui
permet “d’initialiser” ou de “construire” nos objets.

En fait, cette fonction __init__() va être automatiquement exécutée dès qu’on va


instancier la classe. Cette fonction va pouvoir recevoir des arguments qu’on va
lui transmettre durant l’instanciation et qui vont nous permettre de définir des
valeurs propres à chaque instance.

L’idée générale est la suivante : notre fonction __init__() va être construite de


telle sorte à ce que les arguments passés soient utilisés comme valeur
d’initalisation pour les attributs d’une instance. On va passer les argument lors
89
PYTHON

de l’instanciation, via Utilisateur() dans notre cas et ces arguments vont être
transmis à __init__().

Prenons immédiatement un exemple qu’on va expliquer ensuite pour bien


comprendre comment cela se passe :

Notre classe Utilisateur() est désormais composée d’une variable anciennete et


de deux fonctions __init()__ et getNom().

Observons de plus près notre fonction __init__(). Comme vous pouvez le voir,
celle-ci accepte trois paramètres en entrée qu’on a ici nommé self, nom et age.

Il est maintenant temps de vous expliquer ce que signifie ce self qui était déjà
présent dans notre dernière définition de classe. Pour cela, il faut retourner à
notre définition des méthodes.
90
PYTHON

Si vous vous rappelez bien, je vous ai dit au début de cette partie que quasiment
tout en Python était avant tout un objet et qu’en particulier les fonctions étaient
des objets de “type” fonction. Les fonctions d’une classe ne font pas exception :
ce sont également avant tout des objets.

Ces objets fonctions de classes définissent les méthodes correspondantes de ses


instances. Schématiquement, les fonctions des classes deviennent des méthodes
pour les objets créés à partir de cette classe.

Ce que vous devez absolument comprendre ici est qu’une des particularités des
méthodes est que l’objet qui l’appelle est passé comme premier argument de la
fonction telle que définie dans la classe. Ainsi, lorsqu’on écrit pierre.getNom()
par exemple, l’objet pierre est passé de manière implicite à getNom().

C’est la raison pour laquelle nos fonctions de classe possèdent toujours un


paramètre de plus que d’arguments qui leur sont fournies lorsqu’elles sont
appelées en tant que méthode : l’objet qui les appelle prendra la place de ce
paramètre. Par convention, on appelle ce paramètre self qui signifie “soi-même”
pour bien comprendre que c’est l’objet lui même qui va être passé en argument.

Notez ici qu’en Python “self” ne signifie rien et qu’on pourrait tout aussi bien
utiliser un autre nom, à la différence de nombreux autres langages orienté objet
où self est un mot clef réservé.

Revenons en maintenant à notre fonction __init__(). Lorsqu’on instancie notre


classe, c’est-à-dire lorsqu’on crée un nouvel objet à partir de cette classe, la
fonction __init__() est automatiquement appelée si elle est présente dans la
définition de la classe.

Cette fonction va également recevoir l’objet qui est en train d’être créé en
premier argument. Cet objet va donc remplacer le “self”. Ici, notre fonction
__init__() sert à effectuer deux affectations : self.user_name = nom et
self.user_age = age.

Ces deux affectations signifient littéralement “crée un attribut de données


user_name qui sera propre à l’instance et affecte lui la valeur passée en
argument nom” et “crée un attribut de données user_age qui sera propre à
l’instance et affecte lui la valeur passée en argument age”.

Lorsqu’on écrit pierre = Utilisateur("Pierre", 29), les deux arguments passés


“Pierre” et “29” vont être transmis avec l’objet à __init__() qui va les utiliser
pour créer deux attributs de données user_name et user_age spécifique à l’objet
pierre créé.
91
PYTHON

4.2.4 Variables de classe et attributs de données d’un objet

De manière générale, il est considéré comme une bonne pratique de ne créer des
variables de classe que pour définir des variables qui devraient avoir des valeurs
constantes à travers les différents objet de la classe lors de leur création.

Dans l’exemple précédent, par exemple, on peut imaginer que notre classe
Utilisateur nous sert à créer un nouvel objet de type “Utilisateur” dès qu’une
personne s’enregistre sur notre site.

Dans ce cas, l’ancienneté de l’utilisateur au moment de la création de l’objet,


c’est-à-dire au moment de son inscription sera toujours égale à 0 et il fait sens de
définir une variable de classe anciennete.

Retenez également qu’on évitera de créer des variables de classe avec des
données altérables comme des listes ou des dictionnaires sauf dans des cas très
précis. En effet, une variable de classe “appartient” à tous les objets de la classe
par défaut.

Si la variable contient des données altérables, alors n’importe quel objet va


pouvoir modifier ces données. Or, si un objet modifie les données d’une telle
variable de classe, le contenu de la variable sera modifié pour tous les objets de
la classe.

Cela est dû au fait qu’une variable de classe est en fait “partagée” par tous les
objets de la classe. On dit que chaque objet de la classe accède à la variable par
référence.
92
PYTHON

4.3 Héritage et polymorphisme en Python orienté objet


L’héritage et le polymorphisme forment avec le principe d’encapsulation les
trois piliers de la programmation orientée objet. Dans cette leçon, nous allons
présenter et étudier ces concepts en détail et comprendre pourquoi et comment
les implémenter dans notre code.

4.3.1 Présentation du concept d’héritage en Python orienté objet

En programmation orientée objet, “hériter” signifie “avoir également accès à”.


Lorsqu’on dit qu’un objet “hérite” des méthodes de la classe qui l’a défini, cela
signifie que l’objet peut utiliser ces méthodes; qu’il y a accès.

La notion d’héritage va être particulièrement intéressante lorsqu’on va


l’implémenter entre deux classes. En Python, nous allons en effet pouvoir créer
des “sous-classes” ou des classes “enfants” à partir de classes de base ou classes
“parentes”.

La syntaxe pour définir une sous-classe à partir d’une classe de base est la
suivante :

Ici, Utilisateur est notre classe de base et Client est notre sous-classe.

Par défaut, la sous-classe hérite de toutes les variables et fonctions de la classe


parent (et notamment de sa fonction __init__()) et peut également définir ses
93
PYTHON

propres variables et fonctions. On va ensuite pouvoir instancier la classe enfant


pour créer de nouveaux objets et ces objets vont avoir accès aux variables et
fonctions définies à la fois dans la sous-classe et dans la classe de base.

Ce principe d’héritage va nous permettre de créer des classes de base qui vont
définir des fonctionnalités communes à plusieurs classes puis des sous-classes
qui vont hériter de ces fonctionnalités et pouvoir également définir leurs propres
fonctionnalités.

Cela permet in-fine d’obtenir un code plus modulable, mieux organisé, plus clair
et plus concis qui sont des objectifs majeurs pour tout bon développeur.

4.3.2 La surcharge des méthodes de classe

“Surcharger” une méthode signifie la redéfinir d’une façon différente. En


Python, les classes filles ou sous-classes vont pouvoir surcharger les méthodes
héritées de leur classe parent et également pouvoir définir des variables de
même nom que celles de leur classe parent.

On ne parlera de surcharge que pour les méthodes car dans le cas des variables
définir une variable avec le même nom dans la sous-classe correspond
finalement à créer une variable locale à la sous-classe en plus de celle “globale”
(celle disponible dans la classe de base) mais ces deux variables continuent
d’exister à part entière et à être différente tandis que lorsqu’on réécrit une
méthode la nouvelle méthode remplace véritablement l’ancienne pour les objets
de la sous-classe.

Réécrivons notre classe Client() afin de définir certaines variables locales et de


surcharger les méthodes de la classe mère Utilisateur :
94
PYTHON

Notez qu’en pratique, on ne voudra souvent pas simplement réécrire l’intégralité


du code d’une classe mère dans une classe fille (cela signifierait que nos classes
sont mal construites) mais on voudra simplement “étendre” la méthode c’est à
dire lui rajouter des instructions spécifiques pour une classe fille.

On va pouvoir faire cela en appelant la méthode de notre classe mère depuis


notre classe fille avec la syntaxe ClasseDeBase.nomDeMethode(), ce qui va
nous permettre de récupérer l’intégralité du code de la classe mère.

Modifions à nouveau notre classe Client afin d’étendre la fonction __init__() de


la classe mère :
95
PYTHON

4.3.3 Les tests d’héritage Python

A ce niveau du cours, vous pourriez (et devriez) vous poser la question


suivante : comment l’objet fait pour déterminer si il doit utiliser les variables ou
méthodes de sa classe ou de la classe mère dont sa classe hérite ?

La réponse à cette question est très simple : Python va rechercher les variables et
méthodes dans un ordre précis.

Lorsqu’on tente d’afficher le contenu d’un attribut de données ou d’appeler une


méthode depuis un objet, Python va commencer par chercher si la variable ou la
fonction correspondantes se trouvent dans la classe qui a créé l’objet. Si c’est le
cas, il va les utiliser. Si ce n’est pas le cas, il va chercher dans la classe mère de
la classe de l’objet si cette classe possède une classe mère. Si il trouve ce qu’il
cherche, il utilisera cette variable ou fonction. Si il ne trouve pas, il cherchera
dans la classe mère de la classe mère si elle existe et etc.

Python va en fait “remonter” le long de la chaine d’héritage des classes jusqu’à


trouver l’information demandée. Si. Elle n’est jamais trouvée, il renverra
finalement une erreur.
96
PYTHON

Notez ici que Python nous fournit également deux fonctions pour nous permettre
de tester le type d’une instance et l’héritage d’une classe.

La fonction isinstance() permet de tester le type d’une instance, c’est-à-dire le


type d’une objet, c’est-à-dire permet de savoir si un objet appartient à une
certaine classe ou pas. On va lui passer en arguments l’objet dont on souhaite
tester le type et le type qui doit servir de test. Cette fonction renverra True si
l’objet est bien du type passé en second argument ou si il est d’un sous-type
dérivé de ce type ou False sinon.

La fonction issubclass() permet de tester l’héritage d’une classe, c’est-à-dire


permet de savoir si une classe hérite bien d’une autre classe ou pas. On va lui
passer en arguments la classe à tester ainsi qu’une autre classe dont on aimerait
savoir si c’est une classe mère de la classe passée en premier argument ou pas.
La fonction renverra True si c’st le cas ou False sinon.

Ces deux fonctions sont très utiles pour tester rapidement les liens hiérarchiques
entre certaines classes et objets et peuvent aider à comprendre plus facilement
un script complexe qui nous aurait été passé.

4.3.4 Le polymorphisme en Python orienté objet

“Polymorphisme” signifie littéralement “plusieurs formes”. Dans le contexte de


la programmation orientée objet, le polymorphisme est un concept qui fait
référence à la capacité d’une variable, d’une fonction ou d’un objet à prendre
plusieurs formes, c’est-à-dire à sa capacité de posséder plusieurs définitions
différentes.

Pour bien comprendre ce concept, imaginons qu’on définisse une classe


nommée Animaux qui possède des fonctions comme seNourrir(), seDeplacer(),
etc. Notre classe va pouvoir ressembler à ça :
97
PYTHON

Ici, j’utilise un nouveau mot clef pass qui me sert à créer une fonction vide. En
effet, le mot clef pass ne fait strictement rien en Python. On est obligés de
l’utiliser pour créer une fonction vide car si on n’écrit rien dans notre fonction
l’interpréteur Python va renvoyer une erreur.

Ma classe Animaux dispose donc d’une fonction seDeplacer() qui ne contient


pas d’instruction. Maintenant, nous allons créer des sous-classes de Animaux
pour différents animaux : Chien, Aigle et Dauphin par exemple.

Ces trois sous classes vont par défaut hériter des membres de leur classe mère
Animaux et notamment de la méthode seDeplacer(). Ici, chacune de nos sous
classes va implémenter cette méthode différemment, c’est-à-dire va la définir
différemment.

Pour ma classe Chien par exemple, la méthode seDeplacer() va renvoyer une


valeur “courir” tandis que pour Aigle cette méthode va renvoyer une valeur
“voler”. Pour Dauphin, seDeplacer() renverra “nager”.

Ceci est un exemple typique de polymorphisme : plusieurs sous-classes héritent


d’une méthode d’une classe de base qu’ils implémentent de manière différente.

Le polymorphisme permet également in-fine d’obtenir un code plus clair, plus


lisible et plus cohérent : on va pouvoir fournir des définitions de fonctions vides
dans une classe de base afin de laisser des sous-classes implémenter (définir) ces
fonctions de différentes manières.
98
PYTHON

4.3.5 Héritage multiple

Pour terminer cette leçon sur l’héritage et le polymorphisme, il faut savoir que
Python gère également une forme d’héritage multiple.

On parle d’héritage multiple en programmation orientée objet lorsqu’une sous-


classe peut hériter de plusieurs classes mères différentes.

Dans la pratique, l’héritage multiple est une chose très difficile à mettre en place
au niveau du langage puisqu’il faut prendre en charge les cas où plusieurs
classes mères définissent les mêmes variables et fonctions et définir une
procédure pour indiquer de quelle définition la sous-classe héritera.

En Python, dans la majorité des cas, l’héritage va se faire selon l’ordre des
classes mères indiquées et cela de manière récursive. Imaginons qu’une sous-
classe AGrave hérite de trois classes A, Accent et Abracadabra dans cet ordre et
que la classe A hérite elle même de la classe Alphabet tandis que Abracadabra
hérite de Mot

On crée un objet en instanciant notre classe AGrave et on appelle une méthode


depuis notre objet. Python va à priori commencer par chercher la méthode dans
AGrave, puis si il ne la trouve pas cherchera dans A. S’il ne la trouve pas il
cherchera ensuite dans Alphabet, puis dans Accent, puis dans Abracadabra et
finalement dans Mot.

Regardez plutôt le code suivant qui illustre bien cette situation :


99
PYTHON
100
PYTHON

En réalité, Python utilise un algorithme relativement complexe qui détermine


l’ordre d’appel (method resolution order, ou MRO en anglais) de manière
dynamique, c’est-à-dire en fonction des relations entre les différentes classes.

Dans notre exemple, si les classes A, Accent et Abracadabra avaient eu des


parents en commun, l’ordre aurait été beaucoup plus complexe à calculer. Ce
genre de situations arrive très peu fréquemment et est à éviter; un bon
développeur privilégiant toujours la lisibilité de son code et donc je n’en parlerai
pas plus. Si vous souhaitez plus d’informations à ce sujet, je vous invite à vous
renseigner sur l’algorithme C3 utilisé par Python pour déterminer le MRO.

4.4 Gérer la visibilité des membres de classe en Python orienté objet


Dans cette nouvelle leçon liée à l’orienté objet, nous allons voir un autre concept
important de la POO qui concerne l visibilité ou le niveau d’accès des différents
membres de classe.

Nous terminerons cette leçon avec un petit rappel sur “pourquoi coder en orienté
objet” qui, je l’espère, vous permettra de commencer à avoir une vision
d’ensemble claire sur la programmation orientée objet et sur ses objectifs.

4.4.1 Les niveaux de visibilité des membres de classe en programmation


orientée objet

Dans la plupart des langages qui supportent l’orienté objet, on peut définir des
“niveaux de visibilité” ou “niveaux d’accès” pour les membres des classes
(c’est-à-dire pour les variables et les fonctions).

En POO, on distingue généralement trois niveaux de visibilité différents :

 Les membres privés auxquels on ne peut accéder que depuis l’intérieur de


lac classe ;
 Les membres protégés auxquels on ne peut accéder que depuis l’intérieur
de la classe ou depuis une classe fille ;
 Les membres publics auxquels on peut accéder depuis n’importe quelle
instance (ou objet) de la classe ou d’une classe fille.

Ces niveaux de visibilité permettent de “protéger” certains membres de classes


qui ne devraient pas être modifiés dans n’importe quelle situation ou depuis
n’importe quel endroit.

4.4.2 Les niveaux de visibilité des membres de classe en Python


101
PYTHON

Python n’implémente pas directement ces concepts de visibilité des membres de


classe et il est donc impossible de définir un membre comme privé ou protégé :
par défaut, tous les membres de classe sont publics en Python.

En revanche, certaines conventions ont été mises en place par la communauté


Python, notamment au niveau des noms des membres de classe qui servent à
indiquer aux autres développeurs qu’on ne devrait accéder à tel membre que
depuis l’intérieur de la classe ou à tel autre membre que depuis la classe ou une
classe fille.

Attention ici : ce ne sont que des conventions qui n’ont aucun équivalent réel en
Python : on va pouvoir informer d’autres développeurs du niveau de visibilité
souhaité pour un membre mais tous les membres seront toujours publics en
Python et il est de la responsabilité des autres développeurs de suivre nos
indications ou pas.

Ces conventions sont les suivantes :

 On préfixera les noms des membres qu’on souhaite définir comme


“privés” avec deux underscores comme ceci : __nom-du-membre ;
 On préfixera les noms des membres qu’on souhaite définir comme
“protégés” avec un underscore comme ceci : _nom-du-membre.

Il est à noter que ces conventions n’ont pas été adoptées par hasard. En effet,
Python possède un mécanisme appelé “name mangling” qui fait que tout
membre de classe commençant par deux underscores, c’est-à-dire de la forme
__nom-du-membre sera remplacé textuellement lors de l’interprétation par
_nom-de-classe__nom-du-membre.

Cela fait que si un développeur essaie d’utiliser un membre défini avec deux
underscores tel quel, Python renverra une erreur puisqu’il préfixera le nom avec
un underscore et le nom de la classe du membre.

Cette règle a été prévue par Python pour éviter les accidents de conflits entre
plusieurs membres de plusieurs classes qui auraient le même nom. Elle
n’empêche pas d’accéder ou de modifier un membre “privé”. En effet, il suffit
de préfixer le membre de la même façon que Python lors de son interprétation
pour y accéder.

Prenons immédiatement un exemple afin de bien comprendre ce qu’on vient de


dire :
102
PYTHON

On définit ici une classe Visibilite qui contient trois variables public, _protected
et __private. Notez qu’on pourrait aussi bien définir des fonctions de la même
manière.

Maintenant, créons un objet à partir de cette classe et essayons d’afficher les


valeurs de nos variables de classe à partir de l’objet créé :

Comme vous le voyez, on accède sans souci à nos variables public et _protected.
En revanche, pour __private, le mécanisme de name mangling s’active et le nom
passé est préfixé par un underscore et le nom de la classe. On peut cependant
contourner cela et toujours afficher le contenu de la variable privée en utilisant
la notation _Visibiilite__private.

Il est possible que vous ne voyez pas l’intérêt de tout cela si vous n’avez pas
beaucoup d’expérience en programmation. Dans ce cas, il est important de
retenir et de vous persuader qu’une immense partie du travail d’un développeur
est de s’assurer d’avoir un code le plus clair, concis et modulable possible (en
plus d’être fonctionnel bien évidemment). Toutes ces notions liées à l’orienté
objet permettent de servir ces objectifs.

Et si vous vous posez toujours la question : oui, on pourrait arriver à des


résultats similaires en utilisant une approche non orientée objet mais la qualité
générale de notre code serait bien plus mauvaise. De plus, Python nous fournit
de nombreux outils et notamment des méthodes pour les types prédéfinis qui ne
sont accessible qu’en utilisant l’orienté objet et il serait dommage de s’en priver.
103
PYTHON

4.5 Itérateurs et générateurs en Python orienté objet


Les itérateurs permettent de parcourir des valeurs composites itérables (des
objets comme des listes par exemple). Les générateurs permettent de simplifier
la création et l’utilisation d’itérateurs. Dans cette nouvelle leçon, nous allons
détailler le fonctionnement des itérateurs Python et voir comment définir des
générateurs.

4.5.1 Les itérateurs

“Itérer” signifie en français classique “répéter, faire une seconde fois”. Dans le
contexte de la programmation orienté objet, “itérer” sur un objet signifie
parcourir l’objet attribut par attribut pour accéder à leur valeur.

Les itérateurs sont implicitement utilisés chaque fois que nous manipulons des
collections de données comme les list, tuple ou string (qui sont des objets dits
“itérables”).

La méthode habituelle pour parcourir une collection est d’utiliser une boucle for.
Lorsque nous utilisons une boucle for pour parcourir un objet itérable, la boucle
appelle en fait en interne la fonction iter() sur l’objet itérable.

Au lieu d’utiliser la boucle for comme indiqué ci-dessus, nous pouvons utiliser
la fonction itérateur iter(). Un itérateur est un objet qui représente un flux de
données. Il retourne un élément à la fois.

La méthode intégrée Python iter() reçoit un itérable et retourne un objet


itérateur. L’objet itérateur renvoyé définit la méthode __next__() qui va accéder
aux éléments de l’objet itérable un par un.

Chaque fois que __next__() est appelée, l’élément suivant du flux itérateur est
renvoyé. Lorsqu’il n’y a plus d’éléments disponibles, __next__() lève une erreur
StopIteration.

Notez qu’on peut également appeler la méthode __next__() manuellement en


utilisant la fonction next().
104
PYTHON

On va pouvoir définir nos propres itérateurs dans nos classes pour itérer de
manière particulière sur nos objets itérables (en partant de la fin, en sautant des
caractères, etc.).

Pour cela, il suffit de définir une méthode __iter__() qui renvoie un objet
disposant d’une méthode __next__(). Si la classe définit elle-même la méthode
__next__(), alors __iter__() peut simplement renvoyer self.
105
PYTHON

Ici, on crée une classe qui définit un itérateur qui va sauter une donnée de la
séquence sur laquelle il Isère à chaque nouveau passage.

4.5.2 Les générateurs

La création d’itérateurs peut parfois s’avérer complexe ou contraignante. Les


générateurs sont des outils qui nous permettent de créer des itérateurs.

La syntaxe d’un générateur est la même que celle d’une fonction classique à la
différence que les générateurs utilisent l’instruction yield à la place de return
pour retourner des données.

L’instruction yield va mettre le générateur en pause mais le contexte d’exécution


de celui-ci va être conservé, ce qui va nous permettre d’itérer. A chaque fois
106
PYTHON

qu’on appelle un générateur avec next(), le générateur va reprendre son travail


jusqu’au prochain yield.

Lorsqu’on définit un générateur, les méthodes __iter__() et __next__() sont


créées automatiquement. De plus, les variables locales ainsi que le contexte
d’exécution sont sauvegardés automatiquement entre les appels ce qui nous évite
d’avoir à utiliser des notations du type self.attribut. Enfin, les générateurs lèvent
automatiquement une exception StopIteration lorsqu’ils terminent leur
exécution.

Ces fonctionnalités font des générateurs des outils privilégiés pour créer des
itérateurs de manière plus simple.

Annexe 2 : Quelques méthodes Python utiles


En programmation orientée objet, tout élément d’un langage (ou presque) est
objet. En Python, les types de données sont en fait avant tout représenté par des
classes qui déterminent les propriétés et manipulations qu’on va pouvoir faire
sur chaque donnée.

Lorsqu’on crée une liste, un dictionnaire, une chaine de caractères, etc. on crée
avant tout un nouvel objet à partir des classes list, dict, str, etc.
107
PYTHON

La plupart de ces classes définissent des méthodes qui permettent de réaliser des
opérations courantes sur chaque type de donnée. Dans cette leçon, nous allons
passer en revue quelques unes des méthodes qui pourront certainement vous être
utiles par la suite et qu’il faut connaitre pour les types de données str, list, et
dict.

Pour obtenir la liste complète d’un méthode qu’on peut utiliser avec un type de
données, il suffit d’appeler la fonction dir() en lui passant un objet en argument.
108
PYTHON

Note : Les méthodes commençant et finissant par __ (un double underscore)


sont appelées des “méthodes magiques”. Ces méthodes fournissent des
109
PYTHON

fonctionnalités syntaxiques spéciales ou font des choses spéciales.


Généralement, on ne va pas les appeler directement.

Les méthodes des chaines de caractères

Les chaines de caractères Python disposent des méthodes magiques suivantes :


__add__(), __class__(), __contains__(), __delattr__(), __dir__(), __doc__(),
__eq__(), __format__(), __ge__(), __getattribute__(), __getitem__(),
__getnewargs__(), __gt__(), __hash__(), __init__(), __init_subclass__(),
__iter__(), __le__(), __len__(), __lt__(), __mod__(), __mul__(), __ne__(),
__new__(), __reduce__(), __reduce_ex__(), __repr__(), __rmod__(),
__rmul__(), __setattr__(), __sizeof__(), __str__(), __subclasshook__().

On va également pouvoir utiliser les méthodes classiques suivantes sur des


objets Python de type str : capitalize(), casefold(), center(), count(), encode(),
endswith(), expandtabs(), find(), format(), format_map(), index(), isalnum(),
isalpha(), isascii(), isdecimal(), isdigit(), isidentifier(), islower(), isnumeric(),
isprintable(), isspace(), istitle(), isupper(), join(), ljust(), lower(), lstrip(),
maketrans(), partition(), replace(), rfind(), rindex(), rjust(), rpartition(), rsplit(),
rstrip(), split(), splitlines(), startswith(), strip(), swapcase(), title(), translate(),
upper(), zfill().

Parmi les méthodes qu’on va le plus utiliser, on peut mentionner les méthodes
lower(), upper() et capitalize() qui renvoient respectivement une chaine de
caractères en minuscules, majuscules, et avec la première lettre en majuscule.

La méthode replace() effectue un remplacement dans la chaine et renvoie la


chaine modifiée.

La méthode strip() permet de supprimer les espaces superflus en début et en fin


de chaine.

La méthode find() permet de chercher la première occurence d’un caractère ou


d’une séquence de caractères et renvoie leur position.

Les méthodes startswith() et endswith() permettent de vérifier si une chaine


commence ou se termine bien par un caractère ou par une séquence de
caractères et renvoient un booléen.
110
PYTHON

La méthode split() convertit une chaîne en une liste de sous-chaînes. On peut


choisir le caractère séparateur en le fournissant comme argument (par défaut
l’espace est choisi comme séparateur).

La méthode join() est la méthode “contraire” de split() : elle permet de


rassembler un ensemble de chaînes stockées dans un objet itérable (une liste, un
tuple, un dictionnaire…) en une seule.

Attention : la chaîne à laquelle on applique cette méthode est celle qui servira de
séparateur (un ou plusieurs caractères) ; l’argument transmis est la liste des
chaînes à rassembler. Si on lui passe un dictionnaire en argument, les valeurs
retournées seront les clefs du dictionnaire.
111
PYTHON

La méthode format() est une des méthodes qu’il faut absolument connaitre en
Python. Elle permet de formater des chaines de caractères. On va utiliser des
accolades pour définir des parties de chaines qui devront être formatées.

On va ensuite pouvoir utiliser la méthode format() pour formater la chaine en


utilisant les valeurs passées en argument.

On peut également utiliser les expressions formatées en utilisant des noms de


variable et en préfixant notre chaine avec la lettre f.
112
PYTHON

Les méthodes des listes

Les listes Python disposent des méthodes magiques suivantes : __add__(),


__class__(), __contains__(), __delattr__(), __delitem__(), __dir__(), __doc__(),
__eq__(), __format__(), __ge__(), __getattribute__(), __getitem__(), __gt__(),
__hash__(), __iadd__(), __imul__(), __init__(), __init_subclass__(), __iter__(),
__le__(), __len__(), __lt__(), __mul__(), __ne__(), __new__(), __reduce__(),
__reduce_ex__(), __repr__(), __reversed__(), __rmul__(), __setattr__(),
__setitem__(), __sizeof__(), __str__(), __subclasshook__().

Nous allons également pouvoir utiliser les méthodes suivantes avec les listes :
append(), clear(), copy(), count(), extend(), index(), insert(), pop(), remove(),
reverse(), sort.

La méthode append() permet d’ajouter un ou une collection d’éléments en fin de


liste. La liste de départ est modifiée.

La méthode insert() permet elle d’ajouter un ou une collection d’éléments à une


position dans la liste. La position est spécifiée en premier argument tandis que
l’élément à ajouter est spécifié en second argument.

La méthode pop() retire et renvoie l’élément de la liste dont l’index est passé en
argument. Si on ne lui passe pas d’argument, le dernier élément sera supprimé.

La méthode remove() permet de supprimer le premier élément dont la valeur


correspond à la valeur passée en argument de cette méthode.

La méthode clear() permet de supprimer tous les éléments d’une liste.

La méthode sort() permet de classer les éléments d’une liste dans l’ordre
alphabétique. On peut lui passer un argument reverse = True pour que la liste
soit classée dans l’ordre alphabétique inversé (de Z à A).
113
PYTHON

Les méthodes des dictionnaires

Les dictionnaires disposent des méthodes magiques suivantes : __class__(),


__contains__(), __delattr__(), __delitem__(), __dir__(), __doc__(), __eq__(),
__format__(), __ge__(), __getattribute__(), __getitem__(), __gt__(),
__hash__(), __init__(), __init_subclass__(), __iter__(), __le__(), __len__(),
__lt__(), __ne__(), __new__(), __reduce__(), __reduce_ex__(), __repr__(),
__setattr__(), __setitem__(), __sizeof__(), __str__(), __subclasshook__().
114
PYTHON

Nous allons également pouvoir utiliser les méthodes suivantes avec ce type de
données : clear(), copy(), fromkeys(), get(), items(), keys(), pop(), popitem(),
setdefault(), update(), values.

La méthode Python keys() renvoie la liste des clefs utilisées dans un dictionnaire
tandis que la méthode values() renvoie la liste des valeurs d’un dictionnaire. La
méthode get() renvoie elle la valeur de l’élément du dictionnaire possédant la
clef spécifiée.

La méthode items() extrait une liste de tuples à partir d’un dictionnaire.

Enfin, la méthode pop() supprime l’élément du dictionnaire lié à la clef


spécifiée.
115
PYTHON
116
PYTHON

CHAPITRE 5. MODULES STANDARDS ET


PAQUETS PYTHON
5.1 Les modules et paquets Python

5.2 Modules Python standards Math, Random et Statistics

5.3 Les modules Python standards Datetime, Time et Calendar

5.4 Le module Python standard Re – expressions régulières ou rationnelles

5.1 Les modules et paquets Python


Dans cette nouvelle partie, nous allons découvrir une autre facette du langage
Python qui en fait un langage à la fois très puissant, modulable et évolutif :
l’utilisation de modules. Nous allons notamment étudier le fonctionnement de
quelques modules prédéfinis qu’il convient de savoir manipuler.

5.1.1 Définition et cas d’utilisation des modules Python

On appelle “module” tout fichier constitué de code Python (c’est-à-dire tout


fichier avec l’extension .py) importé dans un autre fichier ou script.

Les modules permettent la séparation et donc une meilleure organisation du


code. En effet, il et courant dans un projet de découper son code en différents
fichiers qui vont contenir des parties cohérentes du programme final pour
faciliter la compréhension générale du code, la maintenance et le travail
d’équipe si on travaille à plusieurs sur le projet.

En Python, on peut distinguer trois grandes catégories de module en les classant


selon leur éditeur :

 Les modules standards qui ne font pas partie du langage en soi mais sont
intégrés automatiquement par Python ;
 Les modules développés par des développeurs externes qu’on va pouvoir
utiliser ;
 Les modules qu’on va développer nous mêmes.

Dans tous les cas, la procédure à suivre pour utiliser un mode sera la même.
Nous allons commencer par décrire cette procédure puis nous étudierons dans la
suite de cette partie quelques modules standards qu’il convient de connaitre.

5.1.2 Importer un module


117
PYTHON

Un programme Python va généralement être composé d’un script principal qui


va importer différents modules (c’est-à-dire différents fichiers Python) pour
pouvoir les utiliser.

Pour importer un module, on utilise la syntaxe import nom-de-mon-module.


Pour utiliser les éléments du module dans notre script, il faudra préfixer le nom
de ces éléments par le nom du module et un point. Cela permet d’éviter les
conflits dans le cas où on aurait défini des éléments de même nom que ceux
disponibles dans le module.

Pour comprendre comment cela fonctionne en pratique, je vous invite à ouvrir


votre éditeur de texte et à créer un fichier qu’on va appeler “bonjour”. Notre
fichier va contenir une variable et une fonction comme ceci :

Ensuite, enregistrez le dans le dossier Python que vous devriez avoir créé au
début de ce cours et qui devrait se trouver sur votre bureau.

Dès que tout cela est fait, on peut retourner dans le terminal ou l’invite de
commande. Ne lancez pas l’interpréteur pour le moment et pensez bien à définir
le dossier Python comme dossier de référence pour la recherche de fichiers
Python si ça n’a pas été fait au début de ce cours.

Pour cela, vous pouvez utiliser la commande cd (pour “change directory”) suivie
du chemin du dossier qui doit être le dossier de référence (Desktop/Python pour
Mac par exemple).

On peut ensuite lancer l’interpréteur Python. Ici, il faut imaginer que notre
terminal / invite de commande représente le script principal de notre
programme. On va importer notre module dans ce script principal grâce à
l’instruction import bonjour.

Lorsque l’interprète rencontre une instruction import, il importe le module s’il


est présent dans le path (le chemin de recherche). Pour rappel, le path ou chemin
de recherche est une liste de répertoires dans lesquels l’interpréteur cherche
avant d’importer un module. Pour être tout à fait précis, lorsqu’on importe un
118
PYTHON

module, l’interpréteur Python le recherche dans différents répertoires selon


l’ordre suivant :

1. Le répertoire courant ;
2. Si le module est introuvable, Python recherche ensuite chaque répertoire
listé dans la variable shell PYTHONPATH ;
3. Si tout échoue, Python vérifie le chemin par défaut. Sous UNIX, ce
chemin par défaut est normalement /usr/local/lib/python/.

Dès que notre module est importé, on va pouvoir accéder tout simplement aux
variables et fonctions de notre module depuis notre script en préfixant le nom
des éléments du module par le nom du module et un point comme ceci :

5.1.3 Créer un alias de nom pour un module

On peut utiliser le mot clef as pour renommer un module ou plutôt pour créer un
alias de nom. Cela peut permettre d’obtenir des scripts plus courts et plus clairs
dans le cas où le nom du module est inutilement long ou s’il est peu descriptif.

Note : on ne peut importer un module qu’une fois dans un script. Si vous testez
le code ci-dessus et si vous aviez déjà importé le module précédemment, il
faudra que vous quittiez l’interpréteur et que vous le relanciez pour que tout
fonctionne. Pour quitter l’interpréteur, vous pouvez utiliser l’instruction quit().
119
PYTHON

5.1.4 Importer uniquement certains éléments d’un module

Parfois, nous n’aurons besoin que de certains éléments précis dans un module.
On va alors pouvoir se contenter d’importer ces éléments en particulier. Pou
cela, on va utiliser l’instruction from nom-du-module import un-element.

On va par exemple pouvoir choisir de n’importer que la variable nom ou que la


fonction disBonjour() depuis le module bonjour.py.

Dans le cas où on n’importe que certains éléments depuis un module, il ne


faudra pas ensuite préfixer le nom des éléments par le nom du module pour les
utiliser dans notre script principal.

5.1.5 Obtenir la liste des éléments d’un module

Souvent, on importera des modules standards ou créés par d’autres


développeurs. Dans ce cas là, il peut être intéressant d’obtenir rapidement la liste
des éléments du module afin de voir rapidement ce qui va pouvoir nous être
utile.

Pour faire cela, on peut utiliser la fonction dir() qui renvoie la liste de toutes les
fonctions et variables d’un module.
120
PYTHON

Comme vous pouvez le voir, tout fichier Python possède par défaut des éléments
de configuration.

5.1.6 Les modules Python standards

Comme je vous l’ai dit au début de cette leçon, nous importerons bien souvent
des modules créés par d’autres développeurs ou des modules mis à notre
disposition par Python lui même.

En effet, il existe un grand nombre de modules préconçus et prêts à l’emploi qui


sont fournis d’office avec Python. Ces modules vont étendre le langage et nous
permettre de réaliser toutes sortes d’opérations notamment grâce aux fonctions
qu’ils nous fournissent.

Pour importer un module Python, nous allons à nouveau tout simplement utiliser
une instruction import comme si on importait l’un de nos modules.

Les modules Python standards à connaitre sont les suivants :

 Le module cgi (“Common Gateway Interface” ou “Interface de Passerelle


Commune” en français) fournit des éléments permettant à des
programmes Python de s’exécuter sur des serveurs HTTP ;
 Le module datetime fournit des classes pour manipuler de façon simple ou
plus complexe des dates et des heures ;
 Le module json permet l’encodage et le décodage de données au format
JSON ;
 Le module math fournit un ensemble de fonctions permettant de réaliser
des calculs mathématiques complexes ;
 Le module os fournit une manière portable d’utiliser les fonctionnalités
dépendantes du système d’exploitation ;
 Le module pickle permet de sérialiser des objets Python ;
 Le module random implémente des générateurs de nombres pseudo-
aléatoires pour différentes distributions ;
 Le module re fournit des opérations sur les expressions rationnelles
similaires à celles que l’on trouve dans Perl ;
 Le module socket fournit un accès à l’interface sockets qui correspond à
un ensemble normalisé de fonctions de communication ;
 Le module sys fournit un accès à certaines variables système utilisées et
maintenues par l’interpréteur, et à des fonctions interagissant fortement
avec ce dernier ;
 Les modules urllib.request et urllib.parse permettent d’ouvrir, de lire et
d’analyser des URLs.
121
PYTHON

Vous pouvez retrouver la liste complète des modules standards Python sur le site
officiel.

5.1.7 Les paquets Python

Un paquet est tout simplement un ensemble de plusieurs modules regroupés


entre eux. On va pouvoir importer des paquets de la même façon que des
modules et accéder à un module ou à un élément en particulier en utilisant la
syntaxe nom-paquet.nom-module.nom-element.

5.2 Modules Python standards Math, Random et Statistics


Dans cette leçon, nous allons passer en revue rapidement les trois modules
Python standards math, random et statistics et découvrir leurs fonctionnalités les
plus utilisées.

5.2.1 Le module math

Le module math nous fournit un accès à de nombreuses fonctions permettant de


réaliser des opérations mathématiques comme le calcul d’un sinus, cosinus,
d’une tangente, d’un logarithme ou d’une exponentielle.

Les fonctions les plus couramment utilisées sont les suivantes :

 Les fonctions ceil() et floor() renvoient l’arrondi du nombre passé en


argument en arrondissant respectivement à l’entier supérieur et inférieur ;
 La fonction fabs() renvoie la valeur absolu d’un nombre passé en
argument ;
 La fonction isnan() renvoie True si le nombre passé en argument est NaN
= Not a Number (pas un nombre en français) ou False sinon ;
 La fonction exp() permet de calculer des exponentielles ;
 La fonction log() permet de calculer des logarithmes ;
 La fonction sqrt() permet de calculer la racine carrée d’un nombre ;
 Les fonctions cos(), sin() et tan() permettent de calculer des cosinus, sinus
et tangentes et renvoient des valeurs en radians.

Attention : les fonctions de ce module ne peuvent pas être utilisées avec des
nombres complexes. Pour cela, il faudra plutôt utiliser les fonctions du module
cmath.

Le module math définit également des constantes mathématiques utiles comme


pi ou le nombre de Neper, accessibles via math.pi et math.e.
122
PYTHON

Pour obtenir la liste complète des fonctions et constantes de ce module, je vous


invite à consulter la documentation.

5.2.2 Le module random

Le module random nous fournit des outils pour générer des nombres pseudo-
aléatoires de différentes façons.

La fonction random() est le plus utilisée du module. Elle génère un nombre à


virgule flottante aléatoire de façon uniforme dans la plage semi-ouverte [0.0,
1.0).

La fonction uniform() va elle générer un nombre à virgule flottante aléatoire


compris dans un intervalle. On va lui passer deux tombes en argument : le
premier nombre représente la borne basse de l’intervalle tandis que le second
représente la borne supérieure. Notez que cette fonction se base sur random().
123
PYTHON

Le module random est très riche et contient de nombreuses fonctions qui vont
nous permettre de générer des nombres pseudo aléatoires de différentes
manières et pour différentes situations. Je vous invite à les découvrir en détail
dans la documentation.

5.2.3 Le module statistics

Le module statistics nous fournit des outils nous permettant d’effectuer des
calculs de statistiques peu complexes, comme des calculs de moyenne, de
médiane ou de variance.

Ce module contient notamment les fonctions suivantes :

 La fonction mean() permet de calculer une moyenne ;


 La fonction median() permet de calculer une médiane ;
 La fonction variance() permet de calculer une variance ;
 La fonction stdev() permet de calculer un écart type.
124
PYTHON

Vous pouvez consulter la liste complète des fonctions de ce module ici.

5.2.4 statistics — Fonctions mathématiques pour les statistiques

Nouveau dans la version 3.4.

Code source : Lib/statistics.py

Ce module fournit des fonctions pour le calcul de valeurs statistiques sur des
données numériques (valeurs réelles de la classe Real).

Ce module n'est pas pensé comme substitut à des bibliothèques tierces telles que
NumPy, SciPy ou des suites logicielles propriétaires complètes à destination des
statisticiens professionnels comme Minitab, SAS ou Matlab. Ce module se situe
au niveau des calculatrices scientifiques graphiques.

À moins que cela ne soit précisé différemment, ces fonctions gèrent les objets
int, float, Decimal et Fraction. Leur bon comportement avec d'autres types
(numériques ou non) n'est pas garanti. Le comportement de ces fonctions sur des
collections mixtes de différents types est indéfini et dépend de l'implémentation.
Si vos données comportement un mélange de plusieurs types, vous pouvez
utiliser map() pour vous assurer que le résultat est cohérent, par exemple :
map(float, input_data).

Moyennes et mesures de la tendance centrale

Ces fonctions calculent une moyenne ou une valeur typique à partir d'une
population ou d'un échantillon.
125
PYTHON

mean() Moyenne arithmétique des données.


fmean() Moyenne arithmétique rapide en calcul à virgule flottante.
geometric_mean(
Moyenne géométrique des données.
)
harmonic_mean() Moyenne harmonique des données.
median() Médiane (valeur centrale) des données.
median_low() Médiane basse des données.
median_high() Médiane haute des données.
median_grouped( Médiane de données groupées, calculée comme le 50e
) percentile.
Mode principal (la valeur la plus représentée) de données
mode()
discrètes ou nominales.
Liste des modes (les valeurs les plus représentées) de données
multimode()
discrètes ou nominales.
quantiles() Divise les données en intervalles de même probabilité.

Mesures de la dispersion

Ces fonctions mesurent la tendance de la population ou d'un échantillon à dévier


des valeurs typiques ou des valeurs moyennes.

Écart-type de la
pstdev()
population.
pvariance(
Variance de la population.
)
Écart-type d'un
stdev()
échantillon.
variance() Variance d'un échantillon.

Détails des fonctions

Note : les fonctions ne requièrent pas que les données soient ordonnées.
Toutefois, pour en faciliter la lecture, les exemples utiliseront des séquences
croissantes.

statistics.mean(data)

Renvoie la moyenne arithmétique de l'échantillon data qui peut être une


séquence ou un itérable.
126
PYTHON

La moyenne arithmétique est la somme des valeurs divisée par le nombre


d'observations. Il s'agit de la valeur couramment désignée comme la
« moyenne » bien qu'il existe de multiples façons de définir
mathématiquement la moyenne. C'est une mesure de la tendance centrale
des données.

Une erreur StatisticsError est levée si data est vide.

Exemples d'utilisation :

>>> mean([1, 2, 3, 4, 4])


2.8
>>> mean([-1.0, 2.5, 3.25, 5.75])
2.625

>>> from fractions import Fraction as F


>>> mean([F(3, 7), F(1, 21), F(5, 3), F(1, 3)])
Fraction(13, 21)

>>> from decimal import Decimal as D


>>> mean([D("0.5"), D("0.75"), D("0.625"), D("0.375")])
Decimal('0.5625')

Note

La moyenne arithmétique est fortement impactée par la présence de


valeurs aberrantes et n'est pas un estimateur robuste de la tendance
centrale : la moyenne n'est pas nécessairement un exemple représentatif
de l'échantillon. Voir median() et mode() pour des mesures plus robustes
de la tendance centrale.

La moyenne de l'échantillon est une estimation non biaisée de la moyenne


de la véritable population. Ainsi, en calculant la moyenne sur tous les
échantillons possibles, mean(sample) converge vers la moyenne réelle de
la population entière. Si data est une population entière plutôt qu'un
échantillon, alors mean(data) équivaut à calculer la véritable moyenne μ.

statistics.fmean(data)

Convertit data en nombres à virgule flottante et calcule la moyenne


arithmétique.
127
PYTHON

Cette fonction est plus rapide que mean() et renvoie toujours un float.
data peut être une séquence ou un itérable. Si les données d'entrée sont
vides, la fonction lève une erreur StatisticsError.

>>> fmean([3.5, 4.0, 5.25])


4.25

Nouveau dans la version 3.8.

statistics.geometric_mean(data)

Convertit data en nombres à virgule flottante et calcule la moyenne


géométrique.

La moyenne géométrique mesure la tendance centrale ou la valeur typique


de data en utilisant le produit des valeurs (par opposition à la moyenne
arithmétique qui utilise la somme).

Lève une erreur StatisticsError si les données sont vides, si elles


contiennent un zéro ou une valeur négative. data peut être une séquence
ou un itérable.

Aucune mesure particulière n'est prise pour garantir que le résultat est
parfaitement exact (cela peut toutefois changer dans une version future).

>>> round(geometric_mean([54, 24, 36]), 1)


36.0

Nouveau dans la version 3.8.

statistics.harmonic_mean(data)

Renvoie la moyenne harmonique de data, une séquence ou un itérable de


nombres réels.

La moyenne harmonique est l'inverse de la moyenne arithmétique mean()


des inverses. Par exemple, la moyenne harmonique de trois valeurs a, b et
c vaut 3/(1/a + 1/b + 1/c). Si une des valeurs est nulle, alors le résultat est
zéro.

La moyenne harmonique est un type de moyenne, une mesure de la


tendance centrale des données. Elle est généralement appropriée pour
calculer des moyennes de taux ou de proportions, par exemple des
vitesses.
128
PYTHON

Supposons qu'une voiture parcoure 10 km à 40 km/h puis 10 km à


60 km/h. Quelle a été sa vitesse moyenne ?

>>> harmonic_mean([40, 60])


48.0

Supposons qu'un investisseur achète autant de parts dans trois compagnies


chacune de ratio cours sur bénéfices (P/E) 2,5, 3 et 10. Quel est le ratio
cours sur bénéfices moyen du portefeuille de l'investisseur ?

>>> harmonic_mean([2.5, 3, 10]) # For an equal investment portfolio.


3.6

Une erreur StatisticsError est levée si data est vide ou si l'un de ses
éléments est inférieur à zéro.

L'algorithme actuellement implémenté s'arrête prématurément lors de la


rencontre d'un zéro dans le parcours de l'entrée. Cela signifie que la
validité des valeurs suivantes n'est pas testée (ce comportement est
susceptible de changer dans une version future).

Nouveau dans la version 3.6.

statistics.median(data)

Renvoie la médiane (la valeur centrale) de données numériques en


utilisant la méthode classique « moyenne des deux du milieu ». Lève une
erreur StatisticsError si data est vide. data peut être une séquence ou un
itérable.

La médiane est une mesure robuste de la tendance centrale et est moins


sensible à la présence de valeurs aberrantes que la moyenne. Lorsque le
nombre d'observations est impair, la valeur du milieu est renvoyée :

>>> median([1, 3, 5])


3

Lorsque le nombre d'observations est pair, la médiane est interpolée en


calculant la moyenne des deux valeurs du milieu :

>>> median([1, 3, 5, 7])


4.0
129
PYTHON

Cette approche est adaptée à des données discrètes à condition que vous
acceptiez que la médiane ne fasse pas nécessairement partie des
observations.

Si les données sont ordinales (elles peuvent être ordonnées) mais pas
numériques (elles ne peuvent être additionnées), utilisez median_low() ou
median_high() à la place.

statistics.median_low(data)

Renvoie la médiane basse de données numériques. Lève une erreur


StatisticsError si data est vide. data peut être une séquence ou un itérable.

La médiane basse est toujours une valeur représentée dans les données.
Lorsque le nombre d'observations est impair, la valeur du milieu est
renvoyée. Sinon, la plus petite des deux valeurs du milieu est renvoyée.

>>> median_low([1, 3, 5])


3
>>> median_low([1, 3, 5, 7])
3

Utilisez la médiane basse lorsque vos données sont discrètes et que vous
préférez que la médiane soit une valeur représentée dans vos observations
plutôt que le résultat d'une interpolation.

statistics.median_high(data)

Renvoie la médiane haute des données. Lève une erreur StatisticsError si


data est vide. data peut être une séquence ou un itérable.

La médiane haute est toujours une valeur représentée dans les données.
Lorsque le nombre d'observations est impair, la valeur du milieu est
renvoyée. Sinon, la plus grande des deux valeurs du milieu est renvoyée.

>>> median_high([1, 3, 5])


3
>>> median_high([1, 3, 5, 7])
5

Utilisez la médiane haute lorsque vos données sont discrètes et que vous
préférez que la médiane soit une valeur représentée dans vos observations
plutôt que le résultat d'une interpolation.
130
PYTHON

statistics.median_grouped(data, interval=1)

Renvoie la médiane de données réelles groupées, calculée comme le 50 e


percentile (avec interpolation). Lève une erreur StatisticsError si data est
vide. data peut être une séquence ou un itérable.

>>> median_grouped([52, 52, 53, 54])


52.5

Dans l'exemple ci-dessous, les valeurs sont arrondies de sorte que chaque
valeur représente le milieu d'un groupe. Par exemple 1 est le milieu du
groupe 0,5 - 1, 2 est le milieu du groupe 1,5 - 2,5, 3 est le milieu de 2,5
- 3,5, etc. Compte-tenu des valeurs ci-dessous, la valeur centrale se situe
quelque part dans le groupe 3,5 - 4,5 et est estimée par interpolation :

>>> median_grouped([1, 2, 2, 3, 4, 4, 4, 4, 4, 5])


3.7

L'argument optionnel interval représente la largeur de l'intervalle des


groupes (par défaut, 1). Changer l'intervalle des groupes change bien sûr
l'interpolation :

>>> median_grouped([1, 3, 3, 5, 7], interval=1)


3.25
>>> median_grouped([1, 3, 3, 5, 7], interval=2)
3.5

Cette fonction ne vérifie pas que les valeurs sont bien séparées d'au moins
une fois interval.

CPython implementation detail: Sous certaines conditions,


median_grouped() peut convertir les valeurs en nombres à virgule
flottante. Ce comportement est susceptible de changer dans le futur.

Voir aussi

 Statistics for the Behavioral Sciences, Frederick J Gravetter et


Larry B Wallnau (8e édition, ouvrage en anglais).
 La fonction SSMEDIAN du tableur Gnome Gnumeric ainsi que
cette discussion.

statistics.mode(data)
131
PYTHON

Renvoie la valeur la plus représentée dans la collection data (discrète ou


nominale). Ce mode, lorsqu'il existe, est la valeur la plus représentative
des données et est une mesure de la tendance centrale.

S'il existe plusieurs modes avec la même fréquence, cette fonction renvoie
le premier qui a été rencontré dans data. Utilisez min(multimode(data))
ou max(multimode(data)) si vous désirez le plus petit mode ou le plus
grand mode. Lève une erreur StatisticsError si data est vide.

mode suppose que les données sont discrètes et renvoie une seule valeur.
Il s'agit de la définition usuelle du mode telle qu'enseignée dans à l'école :

>>> mode([1, 1, 2, 3, 3, 3, 3, 4])


3

Le mode a la particularité d'être la seule statistique de ce module à


pouvoir être calculée sur des données nominales (non numériques) :

>>> mode(["red", "blue", "blue", "red", "green", "red", "red"])


'red'

Modifié dans la version 3.8: Gère désormais des jeux de données avec
plusieurs modes en renvoyant le premier mode rencontré. Précédemment,
une erreur StatisticsError était levée si plusieurs modes étaient trouvés.

statistics.multimode(data)

Renvoie une liste des valeurs les plus fréquentes en suivant leur ordre
d'apparition dans data. Renvoie plusieurs résultats s'il y a plusieurs modes
ou une liste vide si data est vide :

>>> multimode('aabbbbccddddeeffffgg')
['b', 'd', 'f']
>>> multimode('')
[]

Nouveau dans la version 3.8.

statistics.pstdev(data, mu=None)

Renvoie l'écart-type de la population (racine carrée de la variance de la


population). Voir pvariance() pour les arguments et d'autres précisions.

>>> pstdev([1.5, 2.5, 2.5, 2.75, 3.25, 4.75])


132
PYTHON

0.986893273527251
statistics.pvariance(data, mu=None)

Renvoie la variance de la population data, une séquence non-vide ou un


itérable de valeurs réelles. La variance, ou moment de second ordre, est
une mesure de la variabilité (ou dispersion) des données. Une variance
élevée indique une large dispersion des valeurs ; une faible variance
indique que les valeurs sont resserrées autour de la moyenne.

Si le second argument optionnel mu est n'est pas spécifié ou est None (par
défaut), il est remplacé automatiquement par la moyenne arithmétique.
Cet argument correspond en général à la moyenne de data. En le
spécifiant autrement, cela permet de calculer le moment de second ordre
autour d'un point qui n'est pas la moyenne.

Utilisez cette fonction pour calculer la variance sur une population


complète. Pour estimer la variance à partir d'un échantillon, utilisez plutôt
variance() à la place.

Lève une erreur StatisticsError si data est vide.

Exemples :

>>> data = [0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25]
>>> pvariance(data)
1.25

Si vous connaissez la moyenne de vos données, il est possible de la passer


comme argument optionnel mu lors de l'appel de fonction pour éviter de
la calculer une nouvelle fois :

>>> mu = mean(data)
>>> pvariance(data, mu)
1.25

La fonction gère les nombres décimaux et les fractions :

>>> from decimal import Decimal as D


>>> pvariance([D("27.5"), D("30.25"), D("30.25"), D("34.5"),
D("41.75")])
Decimal('24.815')

>>> from fractions import Fraction as F


>>> pvariance([F(1, 4), F(5, 4), F(1, 2)])
133
PYTHON

Fraction(13, 72)

Note

Cette fonction renvoie la variance de la population σ² lorsqu'elle est


appliquée sur la population entière. Si elle est appliquée seulement sur un
échantillon, le résultat est alors la variance de l'échantillon s² ou variance
à N degrés de liberté.

Si vous connaissez d'avance la vraie moyenne de la population μ, vous


pouvez utiliser cette fonction pour calculer la variance de l'échantillon
sachant la moyenne de la population en la passante comme second
argument. En supposant que les observations sont issues d'un tirage
aléatoire uniforme dans la population, le résultat sera une estimation non
biaisée de la variance de la population.

statistics.stdev(data, xbar=None)

Renvoie l'écart-type de l'échantillon (racine carrée de la variance de


l'échantillon). Voir variance() pour les arguments et plus de détails.

>>> stdev([1.5, 2.5, 2.5, 2.75, 3.25, 4.75])


1.0810874155219827
statistics.variance(data, xbar=None)

Renvoie la variance de l'échantillon data, un itérable d'au moins deux


valeurs réelles. La variance, ou moment de second ordre, est une mesure
de la variabilité (ou dispersion) des données. Une variance élevée indique
que les données sont très dispersées ; une variance faible indique que les
valeurs sont resserrées autour de la moyenne.

Si le second argument optionnel xbar est spécifié, celui-ci doit


correspondre à la moyenne de data. S'il n'est pas spécifié ou None (par
défaut), la moyenne est automatiquement calculée.

Utilisez cette fonction lorsque vos données forment un échantillon d'une


population plus grande. Pour calculer la variance d'une population
complète, utilisez pvariance().

Lève une erreur StatisticsError si data contient moins de deux éléments.

Exemples :

>>> data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]


134
PYTHON

>>> variance(data)
1.3720238095238095

Si vous connaissez la moyenne de vos données, il est possible de la passer


comme argument optionnel xbar lors de l'appel de fonction pour éviter de
la calculer une nouvelle fois :

>>> m = mean(data)
>>> variance(data, m)
1.3720238095238095

Cette fonction ne vérifie pas que la valeur passée dans l'argument xbar
correspond bien à la moyenne. Utiliser des valeurs arbitraires pour xbar
produit des résultats impossibles ou incorrects.

La fonction gère les nombres décimaux et les fractions :

>>> from decimal import Decimal as D


>>> variance([D("27.5"), D("30.25"), D("30.25"), D("34.5"),
D("41.75")])
Decimal('31.01875')

>>> from fractions import Fraction as F


>>> variance([F(1, 6), F(1, 2), F(5, 3)])
Fraction(67, 108)

Note

Cela correspond à la variance s² de l'échantillon avec correction de Bessel


(ou variance à N-1 degrés de liberté). En supposant que les observations
sont représentatives de la population (c'est-à-dire indépendantes et
identiquement distribuées), alors le résultat est une estimation non biaisée
de la variance.

Si vous connaissez d'avance la vraie moyenne μ de la population, vous


devriez la passer à pvariance() comme paramètre mu pour obtenir la
variance de l'échantillon.

statistics.quantiles(data, *, n=4, method='exclusive')

Divise data en n intervalles réels de même probabilité. Renvoie une liste


de n - 1 valeurs délimitant les intervalles (les quantiles).
135
PYTHON

Utilisez n = 4 pour obtenir les quartiles (le défaut), n = 10 pour obtenir les
déciles et n = 100 pour obtenir les centiles (ce qui produit 99 valeurs qui
séparent data en 100 groupes de même taille). Lève une erreur
StatisticsError si n est strictement inférieur à 1.

data peut être n'importe quel itérable contenant les valeurs de


l'échantillon. Pour que les résultats aient un sens, le nombre
d'observations dans l'échantillon data doit être plus grand que n. Lève une
erreur StatisticsError s'il n'y a pas au moins deux observations.

Les quantiles sont linéairement interpolées à partir des deux valeurs les
plus proches dans l'échantillon. Par exemple, si un quantile se situe à un
tiers de la distance entre les deux valeurs de l'échantillon 100 et 112, le
quantile vaudra 104.

L'argument method indique la méthode à utiliser pour calculer les


quantiles et peut être modifié pour spécifier s'il faut inclure ou exclure les
valeurs basses et hautes de data de la population.

La valeur par défaut pour method est "exclusive" et est applicable pour
des données échantillonnées dans une population dont une des valeurs
extrêmes peut être plus grande (respectivement plus petite) que le
maximum (respectivement le minimum) des valeurs de l'échantillon. La
proportion de la population se situant en-dessous du i e de m valeurs
ordonnées est calculée par la formule i / (m + 1). Par exemple, en
supposant 9 valeurs dans l'échantillon, cette méthode les ordonne et leur
associe les quantiles suivants : 10%, 20%, 30%, 40%, 50%, 60%,
70%, 80%, 90%.

En utilisant "inclusive" comme valeur du paramètre method, on suppose


que data correspond soit à une population entière, soit que les valeurs
extrêmes de la population sont représentées dans l'échantillon. Le
minimum de data est alors considéré comme 0e centile et le maximum
comme 100e centile. La proportion de la population se situant sous la i e
valeur de m valeurs ordonnées est calculée par la formule (i - 1)/(m - 1).
En supposant que l'on a 11 valeurs dans l'échantillon, cette méthode les
ordonne et leur associe les quantiles suivants : 0%, 10%, 20%, 30%, 40%,
50%, 60%, 70%, 80%, 90%, 100%.

# Decile cut points for empirically sampled data


>>> data = [105, 129, 87, 86, 111, 111, 89, 81, 108, 92, 110,
... 100, 75, 105, 103, 109, 76, 119, 99, 91, 103, 129,
... 106, 101, 84, 111, 74, 87, 86, 103, 103, 106, 86,
... 111, 75, 87, 102, 121, 111, 88, 89, 101, 106, 95,
136
PYTHON

... 103, 107, 101, 81, 109, 104]


>>> [round(q, 1) for q in quantiles(data, n=10)]
[81.0, 86.2, 89.0, 99.4, 102.5, 103.6, 106.0, 109.8, 111.0]

Nouveau dans la version 3.8.

Exceptions

Une seule exception est définie :

exception statistics.StatisticsError

Sous-classe de ValueError pour les exceptions liées aux statistiques.

Objets NormalDist

NormalDist est un outil permettant de créer et manipuler des lois normales de


variables aléatoires. Cette classe gère la moyenne et l'écart-type d'un ensemble
d'observations comme une seule entité.

Les lois normales apparaissent dans de très nombreuses applications des


statistiques. Leur ubiquité découle du théorème central limite
<https://fr.wikipedia.org/wiki/Th%C3%A9or%C3%A8me_central_limite>.

class statistics.NormalDist(mu=0.0, sigma=1.0)

Renvoie un nouvel objet NormalDist où mu représente la moyenne


arithmétique et sigma l'écart-type.

Lève une erreur StatisticsError si sigma est négatif.

mean

Attribut en lecture seule correspondant à la moyenne arithmétique d'une


loi normale.

median

Attribut en lecture seule correspondant à la médiane d'une loi normale.

mode

Attribut en lecture seule correspondant au mode d'une loi normale.

stdev
137
PYTHON

Attribut en lecture seule correspondant à l'écart-type d'une loi normale.

variance

Attribut en lecture seule correspondant à la variance d'une loi normale. La


variance est égale au carré de l'écart-type.

classmethod from_samples(data)

Crée une instance de loi normale de paramètres mu et sigma estimés à


partir de data en utilisant fmean() et stdev().

data peut être n'importe quel iterable de valeurs pouvant être converties
en float. Lève une erreur StatisticsError si data ne contient pas au moins
deux éléments car il faut au moins un point pour estimer la moyenne et
deux points pour estimer la variance.

samples(n, *, seed=None)

Génère n valeurs aléatoires suivant une loi normale de moyenne et écart-


type connus. Renvoie une list de float.

Si seed est spécifié, sa valeur est utilisée pour initialiser une nouvelle
instance du générateur de nombres aléatoires. Cela permet de produire des
résultats reproductibles même dans un contexte de parallélisme par fils
d'exécution.

pdf(x)

Calcule la vraisemblance qu'une variable aléatoire X soit proche de la


valeur x à partir de la fonction de densité. Mathématiquement, cela
correspond à la limite de la fraction P(x <= X < x + dx) / dx lorsque dx
tend vers zéro.

La vraisemblance relative est calculée comme la probabilité qu'une


observation appartienne à un intervalle étroit divisée par la largeur de
l'intervalle (d'où l'appellation « densité »). La vraisemblance étant relative
aux autres points, sa valeur peut être supérieure à 1,0.

cdf(x)

Calcule la probabilité qu'une variable aléatoire X soit inférieure ou égale à


x à partir de la fonction de répartition. Mathématiquement, cela
correspond à P(X <= x).
138
PYTHON

inv_cdf(p)

Calcule l'inverse de la fonction de répartition, c'est-à-dire la fonction


quantile. Mathématiquement, il s'agit de x : P(X <= x) = p.

Détermine la valeur x de la variable aléatoire X telle que la probabilité que


la variable soit inférieure ou égale à cette valeur x est égale à p.

overlap(other)

Mesure le recouvrement entre deux lois normales. Renvoie une valeur


réelle entre 0 et 1 indiquant l'aire du recouvrement de deux densités de
probabilité.

quantiles(n=4)

Divise la loi normale entre n intervalles réels équiprobables. Renvoie une


liste de (n - 1) quantiles séparant les intervalles.

Utilisez n = 4 pour obtenir les quartiles (le défaut), n = 10 pour obtenir les
déciles et n = 100 pour obtenir les centiles (ce qui produit 99 valeurs qui
séparent data en 100 groupes de même taille).

Les instances de la classe NormalDist gèrent l'addition, la soustraction, la


multiplication et la division par une constante. Ces opérations peuvent
être utilisées pour la translation ou la mise à l'échelle, par exemple :

>>> temperature_february = NormalDist(5, 2.5) # Celsius


>>> temperature_february * (9/5) + 32 # Fahrenheit
NormalDist(mu=41.0, sigma=4.5)

Diviser une constante par une instance de NormalDist n'est pas pris en
charge car le résultat ne serait pas une loi normale.

Étant donné que les lois normales sont issues des propriétés additives de
variables indépendantes, il est possible d'ajouter ou de soustraite deux
variables normales indépendantes représentées par des instances de
NormalDist. Par exemple :

>>> birth_weights = NormalDist.from_samples([2.5, 3.1, 2.1, 2.4, 2.7,


3.5])
>>> drug_effects = NormalDist(0.4, 0.15)
>>> combined = birth_weights + drug_effects
>>> round(combined.mean, 1)
139
PYTHON

3.1
>>> round(combined.stdev, 1)
0.5

Nouveau dans la version 3.8.

Exemples d'utilisation de NormalDist

NormalDist permet de résoudre aisément des problèmes probabilistes classiques.

Par exemple, sachant que les scores aux examens SAT suivent une loi normale
de moyenne 1060 et d'écart-type 195, déterminer le pourcentage d'étudiants dont
les scores se situent entre 1100 et 1200, arrondi à l'entier le plus proche :

>>> sat = NormalDist(1060, 195)


>>> fraction = sat.cdf(1200 + 0.5) - sat.cdf(1100 - 0.5)
>>> round(fraction * 100.0, 1)
18.4

Déterminer les quartiles et les déciles des scores SAT :

>>> list(map(round, sat.quantiles()))


[928, 1060, 1192]
>>> list(map(round, sat.quantiles(n=10)))
[810, 896, 958, 1011, 1060, 1109, 1162, 1224, 1310]

NormalDist peut générer des observations pour une simulation utilisant la


méthode de Monte-Carlo afin d'estimer la distribution d'un modèle difficile à
résoudre analytiquement :

>>> def model(x, y, z):


... return (3*x + 7*x*y - 5*y) / (11 * z)
...
>>> n = 100_000
>>> X = NormalDist(10, 2.5).samples(n, seed=3652260728)
>>> Y = NormalDist(15, 1.75).samples(n, seed=4582495471)
>>> Z = NormalDist(50, 1.25).samples(n, seed=6582483453)
>>> quantiles(map(model, X, Y, Z))
[1.4591308524824727, 1.8035946855390597, 2.175091447274739]

Les lois normales peuvent être utilisées pour approcher des lois binomiales
lorsque le nombre d'observations est grand et que la probabilité de succès de
l'épreuve est proche de 50%.
140
PYTHON

Par exemple, 750 personnes assistent à une conférence sur le logiciel libre. Il y a
deux salles pouvant chacune accueillir 500 personnes. Dans la première salle a
lieu une présentation sur Python, dans l'autre une présentation à propos de Ruby.
Lors des conférences passées, 65% des personnes ont préféré écouter les
présentations sur Python. En supposant que les préférences de la population
n'ont pas changé, quelle est la probabilité que la salle Python reste en-dessous de
sa capacité d'accueil ?

>>> n = 750 # Sample size


>>> p = 0.65 # Preference for Python
>>> q = 1.0 - p # Preference for Ruby
>>> k = 500 # Room capacity

>>> # Approximation using the cumulative normal distribution


>>> from math import sqrt
>>> round(NormalDist(mu=n*p, sigma=sqrt(n*p*q)).cdf(k + 0.5), 4)
0.8402

>>> # Solution using the cumulative binomial distribution


>>> from math import comb, fsum
>>> round(fsum(comb(n, r) * p**r * q**(n-r) for r in range(k+1)), 4)
0.8402

>>> # Approximation using a simulation


>>> from random import seed, choices
>>> seed(8675309)
>>> def trial():
... return choices(('Python', 'Ruby'), (p, q), k=n).count('Python')
>>> mean(trial() <= k for i in range(10_000))
0.8398

Les lois normales interviennent souvent en apprentissage automatique.

Wikipédia détaille un bon exemple de classification naïve bayésienne. L'objectif


est de prédire le sexe d'une personne à partir de caractéristiques physiques qui
suivent une loi normale, telles que la hauteur, le poids et la pointure.

Nous avons à notre disposition un jeu de données d'apprentissage contenant les


mesures de huit personnes. On suppose que ces mesures suivent une loi normale.
Nous pouvons donc synthétiser les données à l'aide de NormalDist :

>>> height_male = NormalDist.from_samples([6, 5.92, 5.58, 5.92])


>>> height_female = NormalDist.from_samples([5, 5.5, 5.42, 5.75])
>>> weight_male = NormalDist.from_samples([180, 190, 170, 165])
141
PYTHON

>>> weight_female = NormalDist.from_samples([100, 150, 130, 150])


>>> foot_size_male = NormalDist.from_samples([12, 11, 12, 10])
>>> foot_size_female = NormalDist.from_samples([6, 8, 7, 9])

Ensuite, nous rencontrons un nouvel individu dont nous connaissons les


proportions mais pas le sexe :

>>> ht = 6.0 # height


>>> wt = 130 # weight
>>> fs = 8 # foot size

En partant d'une probabilité a priori de 50% d'être un homme ou une femme,


nous calculons la probabilité a posteriori comme le produit de la probabilité
antérieure et de la vraisemblance des différentes mesures étant donné le sexe :

>>> prior_male = 0.5


>>> prior_female = 0.5
>>> posterior_male = (prior_male * height_male.pdf(ht) *
... weight_male.pdf(wt) * foot_size_male.pdf(fs))

>>> posterior_female = (prior_female * height_female.pdf(ht) *


... weight_female.pdf(wt) * foot_size_female.pdf(fs))

La prédiction finale est celle qui a la plus grande probabilité a posteriori. Cette
approche est appelée maximum a posteriori ou MAP :

>>> 'male' if posterior_male > posterior_female else 'female'


'female'

5.3 Les modules Python standards Datetime, Time et Calendar


En programmation, nous sommes souvent amenés à manipuler des dates qui sont
des objets complexes. Python facilite le travail avec les dates en fournissant
l’accès à des modules dont datetime, time et calendar que nous allons étudier
dans cette leçon.

5.3.1 Le module Python standard datetime

Le module datetime est le module de référence pour manipuler les dates et le


temps. Il nous fournit notamment des classes date et time qui vont nous être
précieuses.

Python distingue deux sorte d’objets date et time : les objets “avisés” et les
objets “naifs”. Un objet avisé est un objet qui possède suffisamment de
connaissances internes pour se situer de façon relative par rapport à d’autres
142
PYTHON

objets avisés. Un objet naïf ne comporte pas assez d’informations pour se situer
sans ambiguïté par rapport à d’autres objets date ou time.

Ici, vous pouvez tenir que les objets avisés datetime et time ont un attribut
optionnel d’information sur le fuseau horaire nommé tzinfo. Cet attribut ou objet
tzinfo capture l’information à propos du décalage avec le temps UTC, le nom du
fuseau horaire, et si l’heure d’été est effective.

Le module datetime définit les types suivants :

 date : représente une date; possède des attributs year, month et day ;
 time : représente un temps; possède des attributs hour, minute, second,
microsecond et tzinfo ;
 datetime : combinaison d’une date et d’un temps; possède des attributs
year, month, day, hour, minute, second, microsecond et tzinfo;
 timedelta : représente la différence entre deux objets date, time ou
datetime exprimée en microsecondes ;
 tzinfo : classe de base abstraite (= qui ne peut pas directement être
instanciée) pour les objets portants des informations sur les fuseaux
horaires ;
 timezone : classe qui implémente la classe abstraite <code<tzinfo<
code="">.</code<tzinfo<>

Chaque type (c’est-à-dire chaque classe) va posséder ses fonctions et variables


qui vont nous permettre d’effectuer telle ou telle manipulation sur des dates,
rendant le module datetime très complet.

Voici quelques manipulations courantes qu’on va pouvoir effectuer à partir des


classes du module datetime :
143
PYTHON

Pour une référence complète sur le module Python datetime, je vous invite à
consulter la documentation.

5.3.2 Le module Python standard time

Le module Python time fournit différentes fonctions liées au temps. Il peut et est
généralement utilisé conjointement avec le module datetime. Attention ici à ne
pas confondre le module time et la classe time du module datetime.
144
PYTHON

Le module time possède à nouveau de nombreuses fonctions. Nous allons


rapidement passer en revue les fonctions les plus utilisées. Une nouvelle fois, je
vous invite à consulter la documentation pour plus d’informations sur ce
module.

La fonction time() renvoie le temps en secondes depuis epoch sous forme de


nombre à virgule flottante.

L’epoch correspond au point de départ du temps utilisé comme référence par


votre OS. Il dépend donc de la plate-forme. Pour Unix, epoch est le 1er janvier
1970 à 00:00:00 (UTC). Pour savoir comment est définie epoch sur une plate-
forme donnée, il suffit d’appeler time.gmtime(0).

La fonction gmtime() convertit un temps (passé en argument) exprimé en


secondes depuis epoch en un struct_time au format UTC dans lequel le drapeau
dst est toujours égal à zéro. Si aucun argument ne lui est fourni, l’heure actuelle
telle que renvoyée par time() sera utilisée.

Le DST (Daylight Saving Time) correspond à l’heure d’été, un ajustement du


fuseau horaire d’une heure (généralement) pendant une partie de l’année. Les
règles de DST sont magiques (déterminées par la loi locale) et peuvent changer
d’année en année.

Le struc_time correspond au type de la séquence de valeur temporelle renvoyé


par gmtime(), localtime() et strptime(). Ses valeurs sont accessibles par index et
par nom d’attribut. Les valeurs suivantes sont possibles :

Inde Nom de
Ex de valeur
x l’attribut
0 tm_year 2000, 2010, 2019
1 tm_mon plage [1, 12]
2 tm_mday plage [1, 31]
3 tm_hour plage [0,23]
4 tm_min plage [0,59]
5 tm_sec plage [0,61]
6 tm_wday plage [0, 6], Lundi valant 0
7 tm_yday plage [1, 366]
8 tm_isdst 0, 1 ou -1
abréviation du nom du fuseau
– tm_zone
horaire
décalage à l’est de UTC en
– tm_gmtoff
secondes
145
PYTHON

La fonction localtime() est similaire à gmtime() mais convertit le résultat en


heure locale. On peut lui passer un nombre de secondes représentant une date en
argument. Si aucun argument ne lui est fourni, l’heure actuelle telle que
renvoyée par time() sera utilisée.

La fonction mktime() est la fonction inverse de localtime(). Son argument est


soit un struct_time soit un 9-tuple.

La fonction strptime() analyse une chaîne passée en premier argument


représentant une heure selon un format passé en second argument. La valeur
renvoyée est une valeur struct_time telle que renvoyée par gmtime() ou
localtime().

La fonction strftime() convertit un tuple ou une donnée struct_time passé en


second argument en une chaîne. Le format de la chaine est spécifié par le
premier argument passé à la fonction. Si le temps n’est pas fourni, l’heure
actuelle renvoyée par localtime() est utilisée.

Les directives suivantes peuvent être utilisées dans la chaîne format :

Directiv
Signification
e
%a Nom abrégé du jour de la semaine selon les paramètres régionaux.
%A Le nom de semaine complet de la région.
%b Nom abrégé du mois de la région.
%B Nom complet du mois de la région.
Représentation appropriée de la date et de l’heure selon les paramètres
%c
régionaux.
%d Jour du mois sous forme décimale [01,31].
%H Heure (horloge sur 24 heures) sous forme de nombre décimal [00,23].
%I Heure (horloge sur 12 heures) sous forme de nombre décimal [01,12].
%j Jour de l’année sous forme de nombre décimal [001,366].
%m Mois sous forme décimale [01,12].
%M Minutes sous forme décimale [00,59].
%p L’équivalent local de AM ou PM.
%S Deuxième sous forme de nombre décimal [00,61].
Numéro de semaine de l’année (dimanche en tant que premier jour de la
semaine) sous forme décimale [00,53]. Tous les jours d’une nouvelle
%U
année précédant le premier dimanche sont considérés comme
appartenant à la semaine 0.
%w Jour de la semaine sous forme de nombre décimal [0 (dimanche), 6].
%W Numéro de semaine de l’année (lundi comme premier jour de la
146
PYTHON

Directiv
Signification
e
semaine) sous forme décimale [00,53]. Tous les jours d’une nouvelle
année précédant le premier lundi sont considérés comme appartenant à
la semaine 0.
%x Représentation de la date appropriée par les paramètres régionaux.
%X Représentation locale de l’heure.
%y Année sans siècle comme un nombre décimal [00, 99].
%Y Année complète sur quatre chiffres.
Décalage de fuseau horaire indiquant une différence de temps positive
ou négative par rapport à UTC / GMT de la forme +HHMM ou -
%z
HHMM, où H représente les chiffres des heures décimales et M, les
chiffres des minutes décimales [-23:59, +23:59].
Nom du fuseau horaire (pas de caractères s’il n’y a pas de fuseau
%Z
horaire).
%% Un caractère '%' littéral.

5.3.3 Le module Python standard calendar


147
PYTHON

Le module Python calendar permet d’afficher un calendrier et fournit des


fonctions relatives au calendrier.

Ce module définit une classe Calendar qui va permettre de créer des objets de
type calendrier et une classe TextCalendar qui peut être utilisée pour générer des
calendriers en texte brut.

Les calendriers sont des objets très spécifiques qu’on ne manipule pas tous les
jours et je n’irai donc pas plus loin dans la présentation de ce module. Si vous
avez besoin un jour de créer un calendrier, sachez simplement que ce module
existe. Vous pourrez trouver toutes les informations relatives aux calendriers
Python sur la documentation officielle du module.

5.4 Le module Python standard Re et l’utilisation des expressions régulières


ou rationnelles
Dans cette leçon, nous allons nous intéresser aux expressions rationnelles et au
module Python standard re qui nous permet de les utiliser. Cette leçon n’est pas
un cours sur les expressions rationnelles qui représentent un sujet vaste et
complexe mais simplement une introduction aux possibilités et à l’utilisation de
ces expression dans un contexte Python.

5.4.1 Présentation des expressions régulières ou expressions rationnelles

Les expressions régulières ou expressions rationnelles ne font pas partie du


langage Python en soi mais constituent un langage à part. Python nous permet
d’exploiter leur puissance et fournit un support pour les expressions régulières
via son module standard re.

Les expressions régulières sont des schémas ou des motifs utilisés pour effectuer
des recherches et des remplacements dans des chaines de caractères.

Ces schémas ou motifs sont tout simplement des séquences de caractères dont
certains vont disposer de significations spéciales et qui vont nous servir de
schéma de recherche. On les appelle également des masques de recherche.

Concrètement, les expressions régulières vont nous permettre de vérifier la


présence de certains caractères ou suites de caractères dans une expression afin
de valider la forme de données envoyées par l’utilisateur via une fonction input()
par exemple.

5.4.2 La syntaxe des expressions rationnelles


148
PYTHON

Une expression rationnelle est représentée par un motif de recherche. Ce motif


de recherche va pouvoir être comparée à une ou plusieurs chaines pour
déterminer les correspondances.

Un motif de recherche peut être composés de caractères “normaux”, c’est-à-dire


des caractères qui ne représentent qu’eux mêmes et de caractères “spéciaux”,
c’est-à-dire des caractères qui possèdent une signification spéciale et vont nous
permettre de rechercher autre chose qu’eux mêmes. On appelle également ces
caractères au sens spécial des “métacaractères”.

Ces caractères spéciaux font toute la puissance des expressions rationnelles


puisqu’ils nous permettent de créer des motifs de recherche très précis et
complexes.

Le premier caractère à connaitre est l’antislash \ qui est utilisé par les
expressions rationnelles pour donner un sens spécial à certains caractères
normaux ou au contraire pour neutraliser (“échapper”) le sens d’un caractère
spécial et nous permettre de rechercher le caractère en soi sans qu’il exprime son
sens spécial.

Ici, nous sommes déjà confrontés à un souci puisque Python utilise également
l’antislash comme caractère d’échappement. Pour rechercher un antislash littéral
avec une expression régulière il faudrait donc écrire \\\\ puisque chaque antislash
doit être représenté par \\ dans une chaine littérale Python et que pour rechercher
un antislash (qui est un caractère spécial) dans une expression rationnelle il faut
écrire \\ (le premier antislash servant de caractère d’échappement pour
rechercher le deuxième).

Pour éviter ce genre de situation, on utilisera une notation Python de chaines


brutes plutôt que littérales. Pour cela, il suffira de préfixer la chaine avec un r.

Ensuite, vous devez savoir que certains caractères ne vont avoir un sens spécial
qu’en dehors de ce qu’on appelle des classes de caractères ou vont pouvoir avoir
des sens spéciaux différents selon qu’ils soient dans des classes de caractères ou
en dehors. Commençons déjà par comprendre ce qu’est une classe de
caractères.

5.4.3 Les classes de caractères

Les classes de caractères vont nous permettre de fournir différents choix de


correspondance pour un caractère en spécifiant un ensemble de caractères qui
vont pouvoir être trouvés.
149
PYTHON

En d’autres termes, elles vont nous permettre de rechercher n’importe quel


caractère d’une chaine qui fait partie de la classe de caractères fournie dans le
masque, ce qui va rendre les expressions régulières déjà beaucoup plus
puissantes et flexibles qu’une recherche classique.

Pour déclarer une classe de caractères dans notre masque de recherche, nous
allons utiliser une paire de crochets [ ] qui vont nous permettre de délimiter la
classe en question.

Dans le langage des expressions régulières, de nombreux caractères vont avoir


une signification spéciale et vont nous permettre de signifier qu’on recherche tel
caractères ou telle séquence de caractères un certain nombre de fois ou à une
certaine place dans une chaine.

Au sein des classes de caractères, seuls les caractères suivants possèdent une
signification spéciale :

Métacaractè
Description
re

Caractère de protection ou d’échappement qui va avoir plusieurs


usages (on va pouvoir s’en servir pour donner un sens spécial à des
\
caractères qui n’en possèdent pas ou au contraire pour neutraliser
le sens spécial des métacaractères).

Si placé au tout début d’une classe, permet de nier la classe c’est-à-


^
dire de chercher tout caractère qui n’appartient pas à la classe.

Entre deux caractères, permet d’indiquer un intervalle de


– caractères (correspond à écrire les deux caractères et tous les
caractères entre ces deux là).

Si on souhaite rechercher le caractère représenté par l’un des métacaractères ci-


dessus plutôt que de l’utiliser pour son sens spécial (par exemple si on souhaite
rechercher le signe moins), il faudra alors le protéger ou « l’échapper » avec un
antislash.

Notez qu’il faudra également protéger les caractères de classe (les crochets) si
on souhaite les inclure pour les rechercher dans une classe de caractères car dans
150
PYTHON

le cas contraire on n’aurait aucun moyen de déterminer si le caractère “]” est


recherché ou si la classe est refermée par exemple.

5.4.4 Les classes de caractères abrégées

En plus des classes de caractères “classiques”, les expressions régulières


possèdent également des éléments qu’on appelle classes de caractères abrégées
et qui permettent de représenter certaines classes couramment utilisées avec une
syntaxe très courte.

La syntaxe des classes abrégées utilise l’antislash suivi d’un caractère “normal”
afin de lui donner dans un cas une signification spéciale. Les classes abrégées
les plus intéressantes sont les suivantes (faites bien attention aux emplois de
majuscules et de minuscules ici !) :

Classe abrégée Description

Représente tout caractère de « mot » (caractère alphanumérique +


\w
tiret bas). Équivalent à [a-zA-Z0-9_]

Représente tout caractère qui n’est pas un caractère de « mot ».


\W
Equivalent à [^a-zA- Z0-9_]

\d Représente un chiffre. Équivalent à [0-9]

Représente tout caractère qui n’est pas un chiffre. Équivalent à [^0-


\D
9]

Représente un caractère blanc (espace, retour chariot ou retour à la


\s
ligne)

\S Représente tout caractère qui n’est pas un caractère blanc

\t Représente une espace (tabulation) horizontale

\v Représente une espace verticale

\n Représente un saut de ligne

5.4.5 Les caractères spéciaux en dehors des classe de caractères

En dehors des classes de caractères, nous avons accès à de nombreux autres


caractères au sens spécial. En voici la liste ainsi que leur signification :
151
PYTHON

Métacaractè
Représente
re

. N’importe quel caractère

^ Le début d’une chaine ou d’une ligne

$ La fin d’une chaine ou d’un ligne

| Une alternative : correspond au caractère à droite ou à gauche

* 0, 1 ou plusieurs occurrences

+ 1 ou plusieurs occurrences

? 0 ou 1 occurrence

Un quantificateur : correspond à un nombre n d’occurences d’un


{…}
caractère

Une classe de caractères : tous les caractères énumérés dans la


[…] classe, avec possibilité de plages dont les bornes sont séparées par
« -«

Un groupe de capture : utilisée pour limiter la portée d’un masque


(…)
ou d’une alternative

Note : les expressions rationnelles possèdent également des éléments de syntaxe


plus complexes comme les assertions que nous n’étudierons pas dans ce cours.

5.4.6 Le module Python re et ses fonctions

Maintenant que nous avons (très rapidement) parcouru les éléments de syntaxe
principaux des expressions régulières, il est temps de les utiliser avec le module
re de manière pratique.

Une expression rationnelle en soi n’est qu’un motif. Nous allons donc utiliser
des fonctions qui vont permettre d’effectuer des recherches de motifs dans des
chaines, des remplacements, etc.

La fonction compile() compile un motif vers une expression rationnelle


compilée qu’on va pouvoir utiliser avec les méthodes match() et search().
152
PYTHON

On utilisera compile() lorsqu’on voudra sauvegarder une expression rationnelle


pour la réutiliser dans un programme.

La fonction search() permet d’analyser une chaine passée en deuxième argument


à la recherche du premier emplacement où l’expression rationnelle passé en
premier argument trouve une correspondance, et renvoie l’objet de
correspondance trouvé ou None si aucune position dans la chaîne ne valide le
motif.

La fonction match() prend également un schéma de recherche en premier


argument et une chaine dans laquelle effectuer la recherche en deuxième
argument et renvoie l’objet de correspondance trouvé si zéro ou plus caractères
au début de la chaine correspondent à l’expression rationnelle ou None si la
chaîne ne correspond pas au motif.

La fonction findall() renvoie toutes les correspondances de l’expression


régulière passée en premier argument dans la chaine passée en deuxième
argument qui ne se chevauchent pas, sous forme d’une liste de chaînes. Le
chaîne est analysée de la gauche vers la droite, et les correspondances sont
renvoyées dans l’ordre où elles sont trouvées.
153
PYTHON
154
PYTHON

CHAPITRE 6. MANIPULATION DE FICHIERS


AVEC PYTHON
6.1 Introduction à la manipulation de fichiers en Python

6.2 Opérations sur les fichiers en Python

6.3 L’échange de données en Python avec le module Json

6.1 Introduction à la manipulation de fichiers en Python


Dans cette nouvelle partie, nous allons découvrir un nouveau moyen de stocker
des données de façon durable pour les manipuler par la suite en les stockant dans
des fichiers.

6.1.1 Le stockage des données : variables, fichiers, bases de données

Jusqu’à présent, nous avons utilisé des variables pour stocker des données sous
forme de chaines, de listes, de dictionnaires, etc.

Les variables sont très pratiques car elles vont nous permettre de manipuler nos
données très facilement en Python. Cependant, elles ne vont pas toujours être les
outils les mieux adaptés pour stocker des données.

En effet, le gros “défaut” des variables est qu’elles ne peuvent stocker une
information que temporairement (au mieux le temps de l’exécution d’un script).

Or, dans certains cas, on aimerait enregistrer des informations de manière


définitives, notamment lorsqu’il s’agit d’informations envoyées par les
utilisateurs.

De plus, les variables ne sont pas adaptées pour le stockage de nombreuses


données.

En programmation, pour stocker des informations de manière définitive, on va


pouvoir soit enregistrer ces informations dans des fichiers, soit les enregistrer
dans des bases de données.

De manière générale, les bases de données sont plus puissantes et plus


performantes que le recours aux fichiers pour stocker des informations mais la
gestion d’une base de données est beaucoup plus complexe que l’utilisation de
fichiers.
155
PYTHON

Nous utiliserons donc les fichiers pour des programmes aux ambitions plus
modestes et lorsqu’on n’aura pas de trop grosses quantités d’informations à
stocker et au contraire les bases de données lorsque le besoin d’une structure
plus robuste se fera sentir.

6.1.2 Ouvrir un fichier en Python avec fopen()

Nous allons pouvoir effectuer toutes sortes de manipulations sur nos fichiers en
Python : création d’un fichier, lecture des données, écriture, etc. Pour réaliser
ces opérations, il va cependant avant tout falloir ouvrir le fichier. Pour cela, on
utilise la fonction fopen().

La fonction fopen() renvoie un objet de type “fichier” (type file en anglais).


Cette fonction nous permet d’ouvrir un fichier pour y réaliser différentes
opérations.

On va passer deux arguments à la fonction fopen() : le nom du fichier à ouvrir et


le mode d’ouverture (qui est par défaut r). Ce mode d’ouverture va conditionner
les opérations qui vont pouvoir être faites sur le fichier par la suite. Les modes
d’ouverture les plus utilisés et qui vont nous intéresser sont les suivants :

Mode
Description
d’ouverture

Ouvre un fichier en lecture seule. Il est impossible de modifier le


r
fichier. Le pointeur interne est placé au début du fichier.

Ouvre un fichier en lecture et en écriture. Le pointeur interne est


r+
placé au début du fichier.

Ouvre un fichier en écriture seule en conservant les données


existantes. Le pointeur interne est placé en fin de fichier et les
a
nouvelles données seront donc ajoutées à la fin. Si le fichier
n’existe pas, le crée.

Ouvre un fichier en lecture et en écriture en conservant les données


existantes. Le pointeur interne est placé en fin de fichier et les
a+
nouvelles données seront donc ajoutées à la fin. Si le fichier
n’existe pas, le crée.

w Ouvre un fichier en écriture seule. Si le fichier existe, les


156
PYTHON

Mode
Description
d’ouverture

informations existantes seront supprimées. S’il n’existe pas, crée un


fichier.

Ouvre un fichier en lecture et en écriture. Si le fichier existe, les


w+ informations existantes seront supprimées. S’il n’existe pas, crée un
fichier.

Notez qu’on va également pouvoir rajouter une autre lettre derrière le mode pour
définir si le fichier doit être ouvert en mode texte (lettre t, valeur par défaut ou
en mode binaire (lettre b). Dans ce cours, nous nous concentrerons sur le mode
texte et n’aborderons pas le mode binaire, généralement moins utilisé.

6.1.3 Fermer un fichier

Une fois qu’on a terminé de manipuler un fichier, il est considéré comme une
bonne pratique de le fumer. Cela évite d’utiliser des ressources inutilement et
d’obtenir certains comportements inattendus.

Pour fermer un fichier, on peut soit utiliser la méthode close() soit idéalement
ajouter le mot clef with avant open() lors de l’ouverture du fichier qui garantira
que le fichier sera fermé automatiquement une fois les opérations terminées.

6.1.4 La position du curseur interne ou pointeur

Avant d’aller plus loin dans la manipulation de fichier, il faut que je vous parle
de la position du curseur (ou « pointeur de fichier ») car celle-ci va impacter le
résultat de la plupart des manipulations qu’on va pouvoir effectuer sur les
fichiers. Il est donc essentiel de toujours savoir où se situe ce pointeur et
également de savoir comment le bouger.

Le curseur ou pointeur est l’endroit dans un fichier à partir duquel une opération
va être faite. Pour donner un exemple concret, le curseur dans un document
Word, dans un champ de formulaire ou lorsque vous effectuez une recherche
Google ou tapez une URL dans votre navigateur correspond à la barre
clignotante.

Ce curseur indique l’emplacement à partir duquel vous allez écrire votre requête
ou supprimer un caractère, etc. Le curseur dans les fichiers va être exactement la
même chose à la différence qu’ici on ne peut pas le voir visuellement.
157
PYTHON

Le mode d’ouverture choisi va être la première chose qui va influer sur la


position du pointeur. En effet, selon le mode choisi, le pointeur de fichier va se
situer à une place différente. Ensuite, il faut savoir que certaines méthodes vont
déplacer ce curseur lors de leur exécution, comme les méthodes de lecture du
fichier par exemple.

Pour connaitre la place du pointeur interne dans un fichier et déplacer ce


pointeur, nous allons pouvoir utiliser les méthodes tell() et seek().

La méthode tell() renvoie la position du pointeur interne. La méthode seek()


permet de repositionner ce pointeur.

La méthode fseek() prend deux arguments : le premier argument indique de


combien ou souhaite décaler le curseur interne tandis que le second argument
indique le point de référence à partir d’où décaler le pointeur. Ce point de
référence peut être soit égal à 0 pour le début du fichier, 1 pour la position
actuelle ou 2 pour la fin du fichier.

Cependant, lorsque le fichier est ouvert en mode texte, la méthode seek() ne va


nous offrir que des possibilités limitées.

Entre autre, seek() ne va accepter comme valeur de décalage que 0 ou la valeur


renvoyée par tell() et le point de référence ne pourra être que le début ou la fin
du fichier.

6.2 Opérations sur les fichiers en Python


Dans cette leçon, nous allons apprendre à effectuer toutes sorte d’opérations
avec nos fichiers : écriture dans un fichier, lecture des données d’un fichier,
suppression d’un fichier, etc.

6.2.1 Ecrire dans un fichier en Python

Pour insérer des données dans un fichier, c’est-à-dire pour écrire dans un fichier,
on utilisera la méthode write(). On va passer les données à insérer en argument
de write().

Cette méthode n’accepte que des données de type chaines de caractères : pensez
donc bien à convertir vos données au bon format avant tout.

De plus, notez bien que les données seront écrites à partir de la position du
curseur interne et que si celui-ci est situé au début ou au milieu du fichier les
nouvelles données écraseront les anciennes.
158
PYTHON

Finalement, notez également que write() va renvoyer le nombre de caractères


écrits.

Utilisons immédiatement write() pour écrire le contenu d’une variable dans un


fichier :

6.2.2 Lire les données d’un fichier en Python

Il existe plusieurs façons de lire un fichier en Python. On va pouvoir lire le


fichier entièrement, lire seulement une certaine partie du fichier ou lire le fichier
ligne par ligne. Dès qu’on lit dans un fichier, le curseur interne est déplacé
jusqu’au point de fin de lecture.

Pour lire entièrement un fichier, on peut utiliser la méthode read() sans


argument. Cette méthode renverra le contenu du fichier sous forme de chaine de
caractères.

Pour ne lire qu’une partie d’un fichier, on peut passer un nombre en argument à
read() qui lui indiquera combien de caractères lire à partir de la position
courante du pointeur interne.

Enfin, pour ne lire qu’une ligne d’un fichier, on peut utiliser la méthode
readline().

On peut effectuer différentes opérations sur un fichier à la suite comme par


exemple le créer, écrire dedans puis lire les informations qu’il contient avec la
syntaxe suivante. Attention à la position du curseur !
159
PYTHON

On peut également ouvrir un fichier et écrire dedans puis le refermer et le


réouvrir plus tard pour lire les informations qu’on contient. Dans l’exemple ci-
dessous, je n’utilise plus with ni as. Je place les informations d’ouverture dans
une variable. Il ne faudra pas oublier de fermer le fichier manuellement dans ce
cas avec close() dès nos opérations terminées.
160
PYTHON

6.2.3 Vérifier l’existence d’un fichier

Pour vérifier l’existence d’un fichier, on peut utiliser la fonction exists() du


module path qui appartient au module Python standard os. Cette fonction
renvoie True si le chemin du fichier passé est un chemin qui existe ou False
sinon.

On va pouvoir utiliser cette fonction pour vérifier si un fichier existe et le créer


si ce n’est pas le cas :
161
PYTHON

6.2.4 Supprimer un fichier

Pour supprimer un fichier, on peut utiliser la fonction remove() du module


Python os. On va passer le chemin du fichier à supprimer en argument de celle-
ci.

Ici, on teste si le fichier a bien été supprimé en observant si exists() renvoie bien
False ou pas (note l’utilisation de l’opérateur logique inverse not en début de
condition if).
162
PYTHON

6.3 L’échange de données en Python avec le module Json


Dans cette leçon, nous allons brièvement présenter un format d’échange de
données extrêmement connu dans le monde de la programmation appelé JSON
(JavaScript Object Notation) et voir comment on peut l’utiliser pour échanger
des données Python ou pour recevoir des données JSON et les convertir en
données Python.

6.3.1 Présentation de JSON

JSON (JavaScript Object Notation) est un format d’échange de données dont la


syntaxe s’inspire des objets littéraux JavaScript bien que JSON n’appartienne
pas au JavaScript.

JSON peut représenter des nombres, des booléens, des chaînes, la valeur null,
des séquences de valeurs ordonnées, des objets, etc. JSON ne représente pas
nativement des types de données plus complexes tels que des fonctions, des
expressions régulières, des dates, etc.

La légèreté, la simplicité et les performances de cette notation ont fait de JSON


le standard pour l’échange de données. De nombreux langages -dont Python-
proposent donc aujourd’hui leurs fonctions pour transformer des données en
JSON et inversement.

6.3.2 Le format de données JSON

JSON est un format d’échange de données pensé pour gérer deux structures de
données universelles :

 Une collection de paires nom / valeur. Dans les différentes langages, ce


type de structure peut s’appeler objet, enregistrement, dictionnaire, table
de hachage, liste à clé ou tableau associatif.
 Une liste ordonnée de valeurs. Dans la plupart des langages, c’est ce
qu’on va appeler tableau, liste, vecteur ou séquence.

En JSON, ces deux structures se retrouvent sous les formes suivantes :

 Un objet est un ensemble non ordonnées de paires nom : valeur. Un objet


commence avec { et se termine avec }. Les noms sont suivis de : et les
paires nom : valeur sont séparées par des ,
 Un tableau est une collection ordonnée de valeurs. Un tableau commence
avec [ et se termine avec ]. Les valeurs sont séparées par des ,
163
PYTHON

Une valeur peut être une chaine de caractères entourées par des guillemets
doubles, un nombre, un booléen, la valeur null, un objet ou un tableau.

Exemple de données au format JSON :

6.3.3 Le module Python json

Pour formater des données Python en JSON et inversement, nous allons utiliser
le module Python standard json.

Lorsqu’on encode des données au format JSON, on dit également qu’on


“sérialise” les données. Ce terme fait référence à la transformation de données
en une série d’octets. Le processus inverse de décodage de données encodées au
format JSON est également appelé “désérialisation”.

6.3.4 La sérialisation des données Python

Pour sérialiser des données, c’est-dire pour convertir un objet Python en chaine
JSON, nous allons pouvoir utiliser l’une des méthodes dump() ou dumps() du
module json.
164
PYTHON

La méthode dump() permet d’enregistrer les données JSON dans un fichier


tandis que dumps() (=“dump string”) renvoie simplement les données sous
forme de chaine JSON et nous permet de continuer à travailler avec elles.

Les objets Python vont être convertis selon la table d’équivalence suivante :

Python JSON

dict object

list, tuple array

str string

int, float number

True true

False false

None null

Prenons immédiatement un exemple :


165
PYTHON

Ici, on définit un dictionnaire Python pierre qui contient des données de types
différents.

On ouvre ensuite un fichier “pierre.json” en écriture avec open() puis on écrit les
données sérialisées à l’intérieur grâce à dump(). On passe deux arguments à
dump() : les données à sérialisme et l’objet de type file (fichier) dans lequel elle
doivent être écrites.

On utilise enfin la méthode dumps() pour convertir à nouveau les données en


chaine JSON et on les stocke dans une variable pour pouvoir s’en resservir dans
elle reste du script. On affiche affiche le contenu de la variable qui est bien une
chaine JSON constituée de différentes données formatées selon la table
d’équivalence donnée ci-dessus.

En réalité, vous devez savoir que les méthodes dump() et dumps() acceptent de
nombreux arguments qui vont nous permettre de personnaliser le comportement
et notamment d’arranger nos données comme des arguments de type
“indentation”, “séparateur” ou “classement des clefs” pour indenter les données,
choisir nos séparateurs entre les valeurs ou classer les données par clefs.
166
PYTHON

6.3.5 La désérialisation des données JSON

De la même façon, nous allons pouvoir utiliser l’une des méthodes load() et
loads() pour désérialiser des données JSON, c’st-à-dire pour convertir des
données JSON en objet Python.

La méthode load() permet de désérialiser des données JSON écrites dans un


fichier tandis que loads() permet de désérialiser des données directement sous
forme due chaine JSON.

La table de conversion des donnés va être la même que la précédente. En


reprenant notre exemple suivant, voici le résultat qu’on obtient :
167
PYTHON

Chapitre 7. GESTION DES ERREURS PYTHON


168
PYTHON

CHAPITRE 7. GESTION DES ERREURS


PYTHON
7.1 Introduction à la gestion d’erreurs ou d’exceptions en Python

7.2 Gérer les exceptions en Python avec try, except, else et finally

7.1 Introduction à la gestion d’erreurs ou d’exceptions en Python


En informatique, lors de l’exécution d’un programme, il y a toujours un risque
d’erreur. C’est la raison pour laquelle tout bon langage possède une gestion de
base des erreurs qui correspond concrètement en l’affichage d’un message
d’erreur nous informant sur le type d’erreur détectée et (souvent) en l’arrêt de
l’exécution du programme après que l’erreur ait été détectée.

Dans cette partie, nous allons apprendre à intercepter les erreurs renvoyées par
Python et à les gérer.

7.1.1 Les types d’erreurs et pourquoi gérer les erreurs

On programmation, on peut rencontrer principalement deux types d’erreurs :

 Les erreurs de syntaxe dans le code faites par le développeur ;


 Les erreurs d’environnement qui ne sont pas du fait du développeur.

Par exemple, se servir d’une variable non déclarée dans un script, utiliser des
opérateurs avec des types de données qui ne les supportent pas ou oublier un
guillemet ou un deux points sont des erreurs de syntaxe faites par le
développeur.

En revanche, tenter d’importer un module qui ne serait pas disponible à un


temps t, ou demander à un utilisateur d’envoyer un chiffre et recevoir une chaine
par exemple va produire une erreur qui n’est pas sûr au développeur.

Comme les erreurs de syntaxe sont des erreurs que nous avons faites, nous
pouvons les corriger directement et c’est ce qu’on s’efforcera à faire et
modifiant nos scripts. Pour les autres erreurs, en revanche, il va falloir mettre en
place un système de gestion d’erreurs qui indiquera au Python quoi faire si telle
ou telle erreur est rencontrée.

Il est essentiel de fournir une gestion des erreurs d’environnement afin de


garantir que le script ne plante pas dans certaines situations et pour garantir
169
PYTHON

l’intégrité et la sécurité des données ainsi qu’une bonne expérience pour


l’utilisateur qui n’a pas envie de voir des messages d’erreur Python.

En Python, nous allons pouvoir intercepter certaines erreurs pour les prendre en
charge nous mêmes et pour décider si le script doit continuer de s’exécuter ou
pas.

7.1.2 Les classes exception

En Python, les erreurs détectées durant l’exécution d’un script sont appelées des
exceptions car elles correspondent à un état “exceptionnel” du script.

Si vous essayez de déclencher des erreurs manuellement, vous pouvez constater


que Python analyse le type d’erreur et renvoie un message différent selon
l’erreur détectée :

Ici, nous avons trois types d’exceptions différentes : une exception NameError,
une exception ZeroDivisionError et une exception TypeError. Comment fait
Python pour analyser les types d’erreurs et renvoyer des messages différents en
fonction ?

En fait, vous devez savoir que Python possède de nombreuses classes


d’exceptions natives et que toute exception est une instance (un objet) créé à
partir d’une classe exception.

Afin de bien comprendre la hiérarchie des classes d’exceptions, vous pouvez


retenir que la classe d’exception de base pour les exceptions natives est
BaseException. Toutes les autres classes d’exception vont dériver de cette
170
PYTHON

classe. Ensuite, nous avons également quatre autres classes d’exception de base
(qui dérivent de BaseException) :

 La classe Exception est la classe de base pour toutes les exceptions


natives qui n’entraînent pas une sortie du système et pour toutes les
exceptions définies par l’utilisateur (nous sommes l’utilisateur dans ce
cas) ;
 La classe ArithmeticError est la classe de base pour les exceptions natives
qui sont levées pour diverses erreurs arithmétiques et notamment pour les
classes OverflowError, ZeroDivisionError et FloatingPointError ;
 La classe BufferError est la classe de base pour les exceptions levées
lorsqu’une opération liée à un tampon (“buffer”) ne peut pas être exécutée
;
 La classe LookupError est la classe de base pour les exceptions qui sont
levées lorsqu’une clé ou un index utilisé sur un tableau de
correspondances ou une séquence est invalide.

De nombreuses classes dérivent ensuite de ces classes de base. En fonction de


l’erreur rencontrée par l’analyseur Python, un objet exception appartenant à telle
ou telle classe exception va être crée et renvoyé. C’est cet objet là que nous
allons pouvoir intercepter et manipuler.

Pour la liste complète des classes d’exception, vous pouvez consulter la


documentation.

7.1.3 Exceptions natives

En python, une exception est une instance d'une classe héritée de


BaseException. Dans un bloc try, la clause except traite non seulement la classe
d'exception qu'elle mentionne, mais aussi toutes les classes dérivées de cette
classe (contrairement à ses classes mères). Deux classes qui ne sont pas liées par
héritage ne sont jamais équivalentes, même si elles ont le même nom.

Les exceptions natives présentes ci-dessous peuvent être levées par l'interpréteur
ou par les fonctions natives. Sauf mention contraire, une "valeur associée"
indique la cause de l'erreur. Cela peut être une chaîne ou un tuple contenant
plusieurs éléments d'information (e.g., un code d'erreur ou un message
explicatif). Cette valeur associée est généralement donnée en argument du
constructeur de la classe.

Du code utilisateur peut lever des exceptions natives. Cela peut être utilisé pour
tester un gestionnaire d'exception ou pour rapporter une condition d'erreur
171
PYTHON

"comme si" c'était l'interpréteur qui levait cette exception ; mais attention car
rien n'empêche du code utilisateur de lever une erreur inappropriée.

Les classes d'exception natives peuvent être héritées pour définir de nouvelles
exceptions ; les programmeurs sont encouragés à faire dériver les nouvelles
exceptions de la classe Exception ou d'une de ses sous-classes, et non de
BaseException. Plus d'informations sur la définition des exceptions sont
disponibles dans le Tutoriel Python au chapitre Exceptions définies par
l'utilisateur.

En levant (ou levant à nouveau) une exception dans une clause except ou finally,
__context__ est automatiquement assigné à la dernière exception interceptée ; si
la nouvelle exception n'est pas gérée, la trace d'appels affichée inclut la ou les
exception(s) d'origine et l'exception finale.

En levant une nouvelle exception (plutôt que d'utiliser un simple raise pour lever
à nouveau l'exception en cours de traitement), le contexte implicite d'exception
peut être complété par une cause explicite en utilisant from avec raise :

raise new_exc from original_exc

L'expression suivant from doit être une exception ou None. Elle sera assignée en
tant que __cause__ dans l'exception levée. Changer __cause__ change aussi
implicitement l'attribut __suppress_context__ à True, de sorte que l'utilisation de
raise new_exc from None remplace bien l'ancienne exception avec la nouvelle à
des fins d'affichage (e.g., convertir KeyError en AttributeError), tout en laissant
l'ancienne exception disponible dans __context__ pour introspection lors du
débogage.

Le code d'affichage par défaut de la trace d'appels montre ces exceptions


chaînées en plus de la trace de l'exception elle-même. Si elle est présente, une
exception chaînée explicitement dans __cause__ est toujours affichée. Une
exception implicitement chaînée dans __context__ n'est affichée que si
__cause__ est None et __suppress_context__ est faux.

Dans les deux cas, l'exception elle-même est toujours affichée après toutes les
exceptions enchaînées, de sorte que la dernière ligne de la trace d'appels montre
toujours la dernière exception qui a été levée.

7.1.4 Classes de base

Les exceptions suivantes sont utilisées principalement en tant que classes de


base pour d'autres exceptions.
172
PYTHON

exception BaseException

La classe de base pour toutes les exceptions natives. Elle n'est pas vouée à
être héritée directement par des classes utilisateur (pour cela, utilisez
Exception). Si str() est appelée sur une instance de cette classe, la
représentation du ou des argument(s) de l'instance est retournée, ou la
chaîne vide s'il n'y avait pas d'arguments.

args

Le tuple d'arguments donné au constructeur d'exception. Certaines


exceptions natives (comme OSError) attendent un certain nombre
d'arguments et attribuent une signification spéciale aux éléments de ce
tuple, alors que d'autres ne sont généralement appelées qu'avec une seule
chaîne de caractères rendant un message d'erreur.

with_traceback(tb)

Cette méthode définit tb en tant que nouvelle trace d'appels pour


l'exception et retourne l'objet exception. Elle est généralement utilisée
dans du code de gestion d'exceptions comme ceci :

try:
...
except SomeException:
tb = sys.exc_info()[2]
raise OtherException(...).with_traceback(tb)
exception Exception

Toutes les exceptions natives, qui n'entraînent pas une sortie du système
dérivent de cette classe. Toutes les exceptions définies par l'utilisateur
devraient également être dérivées de cette classe.

exception ArithmeticError

La classe de base pour les exceptions natives qui sont levées pour diverses
erreurs arithmétiques : OverflowError, ZeroDivisionError,
FloatingPointError.

exception BufferError

Levée lorsqu'une opération liée à un tampon ne peut pas être exécutée.

exception LookupError
173
PYTHON

La classe de base pour les exceptions qui sont levées lorsqu'une clé ou un
index utilisé sur un tableau de correspondances ou une séquence est
invalide : IndexError, KeyError. Peut être levée directement par
codecs.lookup().

7.1.5 Exceptions concrètes

Les exceptions suivantes sont celles qui sont habituellement levées.

exception AssertionError

Levée lorsqu'une instruction assert échoue.

exception AttributeError

Levée lorsqu'une référence ou une assignation d'attribut (voir Références


à des attributs) échoue. (Lorsqu'un objet ne supporte pas du tout la
référence ou l'assignation d'attribut, TypeError est levé.)

exception EOFError

Levée lorsque la fonction input() atteint une condition de fin de fichier


(EOF) sans lire aucune donnée. (N.B.: les méthodes io.IOBase.read() et
io.IOBase.readline() retournent une chaîne vide lorsqu'elles atteignent
EOF.)

exception FloatingPointError

N’est pas utilisé pour le moment.

exception GeneratorExit

Levée lorsqu'un generator ou une coroutine est fermé, voir


generator.close() et coroutine.close(). Elle hérite directement de
BaseException au lieu de Exception puisqu'il ne s'agit pas techniquement
d'une erreur.

exception ImportError

Levée lorsque l'instruction import a des problèmes pour essayer de


charger un module. Également levée lorsque Python ne trouve pas un nom
dans from ... import.
174
PYTHON

Les attributs name et path peuvent être définis uniquement à l'aide


d'arguments mot-clef (kwargs) passés au constructeur. Lorsqu'ils sont
définis, ils représentent respectivement le nom du module qui a été tenté
d'être importé et le chemin d'accès au fichier qui a déclenché l'exception.

Modifié dans la version 3.3: Ajout des attributs name et path.

exception ModuleNotFoundError

Une sous-classe de ImportError qui est levée par import lorsqu'un module
n'a pas pu être localisé. Elle est généralement levée quand None est trouvé
dans sys.modules.

Nouveau dans la version 3.6.

exception IndexError

Levée lorsqu'un indice de séquence est hors de la plage. (Les indices de


tranches (slices) sont tronqués silencieusement pour tomber dans la plage
autorisée ; si un indice n'est pas un entier, TypeError est levée.)

exception KeyError

Levée lorsqu'une clef (de dictionnaire) n'est pas trouvée dans l'ensemble
des clefs existantes.

exception KeyboardInterrupt

Levée lorsque l'utilisateur appuie sur la touche d'interruption


(normalement Control-C or Delete). Pendant l'exécution, un contrôle des
interruptions est effectué régulièrement. L'exception hérite de
BaseException afin de ne pas être accidentellement interceptée par du
code qui intercepte Exception et ainsi empêcher l'interpréteur de quitter.

exception MemoryError

Levée lorsqu'une opération est à court de mémoire mais que la situation


peut encore être rattrapée (en supprimant certains objets). La valeur
associée est une chaîne de caractères indiquant quel type d'opération
(interne) est à court de mémoire. À noter qu'en raison de l'architecture
interne de gestion de la mémoire (la fonction malloc() du C), l'interpréteur
peut ne pas toujours être capable de rattraper cette situation ; il lève
néanmoins une exception pour qu'une pile d'appels puisse être affichée,
dans le cas où un programme en cours d'exécution en était la cause.
175
PYTHON

exception NameError

Levée lorsqu'un nom local ou global n'est pas trouvé. Ceci ne s'applique
qu'aux noms non qualifiés. La valeur associée est un message d'erreur qui
inclut le nom qui n'a pas pu être trouvé.

exception NotImplementedError

Cette exception est dérivée de RuntimeError. Dans les classes de base


définies par l'utilisateur, les méthodes abstraites devraient lever cette
exception lorsqu'elles nécessitent des classes dérivées pour remplacer la
méthode, ou lorsque la classe est en cours de développement pour
indiquer que l'implémentation concrète doit encore être ajoutée.

Note

Elle ne devrait pas être utilisée pour indiquer qu'un opérateur ou qu'une
méthode n'est pas destiné à être pris en charge du tout -- dans ce cas,
laissez soit l'opérateur / la méthode non défini, soit, s'il s'agit d'une sous-
classe, assignez-le à None.

Note

NotImplementedError et NotImplemented ne sont pas interchangeables,


même s'ils ont des noms et des objectifs similaires. Voir NotImplemented
pour des détails sur la façon de les utiliser.

exception OSError([arg])

exception OSError(errno, strerror[, filename[, winerror[, filename2]]])

Cette exception est levée lorsqu'une fonction système retourne une erreur
liée au système, incluant les erreurs entrées-sorties telles que "fichier non
trouvé" ou "disque plein" (pas pour les types d'arguments illégaux ou
d'autres erreurs accidentelles).

La deuxième forme du constructeur définit les attributs correspondants,


décrits ci-dessous. Les attributs par défaut sont None si non spécifiés.
Pour la rétrocompatibilité, si trois arguments sont passés, l'attribut args
contient seulement un tuple à deux valeurs des deux premiers arguments
du constructeur.

Le constructeur retourne souvent une sous-classe d' OSError, comme


décrit dans OS exceptions ci-dessous. La sous-classe particulière dépend
176
PYTHON

de la valeur finale d'errno. Ce comportement ne se produit que lors de la


construction d'OSError directement ou via un alias, et n'est pas hérité lors
du sous-classement.

errno

Code d'erreur numérique de la variable C errno.

winerror

Sous Windows, cela donne le code d'erreur Windows natif. L'attribut


errno est alors une traduction approximative, en termes POSIX, de ce
code d'erreur natif.

Sous Windows, si l'argument du constructeur winerror est un entier,


l'attribut errno est déterminé à partir du code d'erreur Windows, et
l'argument errno est ignoré. Sur d'autres plateformes, l'argument winerror
est ignoré, et l'attribut winerror n'existe pas.

strerror

Le message d'erreur correspondant, tel que fourni par le système


d'exploitation. Il est formaté par les fonctions C perror() sous POSIX, et
FormatMessage() sous Windows.

filename

filename2

Pour les exceptions qui font référence à un chemin d'accès au système de


fichiers (comme open() ou os.unlink()), filename est le nom du fichier
transmis à la fonction. Pour les fonctions qui font référence à deux
chemins d'accès au système de fichiers (comme os.rename()), filename2
correspond au deuxième nom de fichier passé à la fonction.

Modifié dans la version 3.3: EnvironmentError, IOError, WindowsError,


socket.error, select.error et mmap.error ont fusionnées en OSError, et le
constructeur peut renvoyer une sous-classe.

Modifié dans la version 3.4: L'attribut filename est maintenant le nom du


fichier originel passé à la fonction, au lieu du nom encodé ou décodé à
partir de l'encodage du système de fichiers. De plus, l'argument du
constructeur et attribut filename2 a été ajouté.
177
PYTHON

exception OverflowError

Levée lorsque le résultat d'une opération arithmétique est trop grand pour
être représenté. Cela ne peut pas se produire pour les entiers (qui préfèrent
lever MemoryError plutôt que d'abandonner). Cependant, pour des raisons
historiques, OverflowError est parfois levée pour des entiers qui sont en
dehors d'une plage requise. En raison de l'absence de normalisation de la
gestion des exceptions de virgule flottante en C, la plupart des opérations
en virgule flottante ne sont pas vérifiées.

exception RecursionError

Cette exception est dérivée de RuntimeError. Elle est levée lorsque


l'interpréteur détecte que la profondeur de récursivité maximale (voir
sys.getrecursionlimit()) est dépassée.

Nouveau dans la version 3.5: Auparavant, une simple RuntimeError était


levée.

exception ReferenceError

Cette exception est levée lorsqu'un pointeur faible d'un objet proxy, créé
par la fonction weakref.proxy(), est utilisé pour accéder à un attribut du
référent après qu'il ait été récupéré par le ramasse-miettes. Pour plus
d'informations sur les pointeurs faibles, voir le module weakref.

exception RuntimeError

Levée lorsqu'une erreur qui n'appartient à aucune des autres catégories est
détectée. La valeur associée est une chaîne de caractères indiquant
précisément ce qui s'est mal passé.

exception StopIteration

Levée par la fonction native next() et la méthode __next__() d'un iterator


(itérateur) pour signaler qu'il n'y a pas d'autres éléments produits par
l'itérateur.

L'objet exception a un unique attribut value, qui est donné en argument


lors de la construction de l'exception, et vaut None par défaut.

Lorsqu'une fonction de type generator ou coroutine retourne une valeur,


une nouvelle instance de StopIteration est levée, et la valeur retournée par
la fonction est passée au paramètre value du constructeur de l'exception.
178
PYTHON

Si le code d'un générateur lève, directement ou indirectement, une


StopIteration, elle est convertie en RuntimeError (en conservant
StopIteration comme cause de la nouvelle exception).

Modifié dans la version 3.3: Ajout de l'attribut value et de la possibilité


pour les fonctions de générateur de l'utiliser pour retourner une valeur.

Modifié dans la version 3.5: Introduit la transformation des erreurs


RuntimeError via from __future__ import generator_stop, cf. PEP 479.

Modifié dans la version 3.7: Active PEP 479 pour tout le code par
défaut : quand une erreur StopIteration est levée dans un générateur elle
est transformée en une RuntimeError.

exception StopAsyncIteration

Doit être levée par la méthode __anext__() d'un objet asynchronous


iterator pour arrêter l'itération.

Nouveau dans la version 3.5.

exception SyntaxError

Levée lorsque l'analyseur syntaxique rencontre une erreur de syntaxe.


Cela peut se produire dans une instruction import, dans un appel aux
fonctions natives exec() ou eval(), ou lors de la lecture du script initial ou
de l'entrée standard (également de manière interactive).

Les instances de cette classe ont des attributs filename, lineno, offset et
text pour accéder plus facilement aux détails. La représentation str() de
l'instance de l'exception retourne seulement le message.

exception IndentationError

Classe de base pour les erreurs de syntaxe liées à une indentation


incorrecte. C'est une sous-classe de SyntaxError.

exception TabError

Levée lorsqu'une indentation contient une utilisation incohérente des


tabulations et des espaces. C'est une sous-classe de IndentationError.

exception SystemError
179
PYTHON

Levée lorsque l'interpréteur trouve une erreur interne, mais que la


situation ne semble pas si grave au point de lui faire abandonner tout
espoir. La valeur associée est une chaîne de caractères indiquant l'erreur
qui est survenue (en termes bas niveau).

Vous devriez le signaler à l'auteur ou au responsable de votre interpréteur


Python. Assurez-vous de signaler la version de l'interpréteur ( sys.version ;
elle est également affichée au lancement d'une session interactive), le
message d'erreur exact (la valeur associée à l'exception) et si possible le
code source du programme qui a déclenché l'erreur.

exception SystemExit

Cette exception est levée par la fonction sys.exit(). Elle hérite de


BaseException au lieu d'Exception pour ne pas qu'elle soit interceptée
accidentellement par du code qui intercepte Exception. Cela permet à
l'exception de se propager correctement et de faire quitter l'interpréteur.
Lorsqu'elle n'est pas gérée, l'interpréteur Python quitte ; aucune trace
d'appels n'est affichée. Le constructeur accepte le même argument
optionnel passé à sys.exit(). Si la valeur est un entier, elle spécifie l'état de
sortie du système (passé à la fonction C exit()) ; si elle est None, l'état de
sortie est zéro ; si elle a un autre type (comme une chaîne de caractères),
la valeur de l'objet est affichée et l'état de sortie est un.

Un appel à sys.exit() est traduit en une exception pour que les


gestionnaires de nettoyage (les clauses finally des instructions try)
puissent être exécutés, et pour qu'un débogueur puisse exécuter un script
sans courir le risque de perdre le contrôle. La fonction os._exit() peut être
utilisée s'il est absolument nécessaire de sortir immédiatement (par
exemple, dans le processus enfant après un appel à os.fork()).

code

L'état de sortie ou le message d'erreur passé au constructeur. ( None par


défaut.)

exception TypeError

Levée lorsqu'une opération ou fonction est appliquée à un objet d'un type


inapproprié. La valeur associée est une chaîne de caractères donnant des
détails sur le type d'inadéquation.

Cette exception peut être levée par du code utilisateur pour indiquer
qu'une tentative d'opération sur un objet n'est pas prise en charge, et n'est
180
PYTHON

pas censée l'être. Si un objet est destiné à prendre en charge une opération
donnée mais n'a pas encore fourni une implémentation, lever
NotImplementedError est plus approprié.

Le passage d'arguments du mauvais type (e.g. passer une list quand un int
est attendu) devrait résulter en un TypeError, mais le passage d'arguments
avec la mauvaise valeur (e.g. un nombre en dehors des limites attendues)
devrait résulter en une ValueError.

exception UnboundLocalError

Levée lorsqu'une référence est faite à une variable locale dans une
fonction ou une méthode, mais qu'aucune valeur n'a été liée à cette
variable. C'est une sous-classe de NameError.

exception UnicodeError

Levée lorsqu'une erreur d'encodage ou de décodage liée à Unicode se


produit. C'est une sous-classe de ValueError.

UnicodeError a des attributs qui décrivent l'erreur d'encodage ou de


décodage. Par exemple, err.object[err.start:err.end] donne l'entrée
particulière invalide sur laquelle le codec a échoué.

encoding

Le nom de l'encodage qui a provoqué l'erreur.

reason

Une chaîne de caractères décrivant l'erreur de codec spécifique.

object

L'objet que le codec essayait d'encoder ou de décoder.

start

Le premier index des données invalides dans object.

end

L'index après la dernière donnée invalide dans object.


181
PYTHON

exception UnicodeEncodeError

Levée lorsqu'une erreur liée à Unicode se produit durant l'encodage. C'est


une sous-classe d'UnicodeError.

exception UnicodeDecodeError

Levée lorsqu'une erreur liée à Unicode se produit durant le décodage.


C'est une sous-classe d'UnicodeError.

exception UnicodeTranslateError

Levée lorsqu'une erreur liée à Unicode se produit durant la traduction.


C'est une sous-classe d'UnicodeError.

exception ValueError

Levée lorsqu'une opération ou fonction native reçoit un argument qui


possède le bon type mais une valeur inappropriée, et que la situation n'est
pas décrite par une exception plus précise telle que IndexError.

exception ZeroDivisionError

Levée lorsque le second argument d'une opération de division ou d'un


modulo est zéro. La valeur associée est une chaîne indiquant le type des
opérandes et de l'opération.

Les exceptions suivantes sont conservées pour la compatibilité avec les


anciennes versions ; depuis Python 3.3, ce sont des alias d'OSError.

exception EnvironmentError

exception IOError

exception WindowsError

Seulement disponible sous Windows.

7.1.6 Exceptions système

Les exceptions suivantes sont des sous-classes d' OSError, elles sont levées en
fonction du code d'erreur système.

exception BlockingIOError
182
PYTHON

Levée lorsqu'une opération bloque sur un objet (par exemple un


connecteur) configuré pour une opération non-bloquante. Correspond à
errno EAGAIN, EALREADY, EWOULDBLOCK et EINPROGRESS.

En plus de ceux de OSError, BlockingIOError peut avoir un attribut de


plus :

characters_written

Un nombre entier contenant le nombre de caractères écrits dans le flux


avant qu'il ne soit bloqué. Cet attribut est disponible lors de l'utilisation
des classes tampon entrées-sorties du module io.

exception ChildProcessError

Levée lorsqu'une opération sur un processus enfant a échoué. Correspond


à errno ECHILD.

exception ConnectionError

Une classe de base pour les problèmes de connexion.

Les sous-classes sont BrokenPipeError, ConnectionAbortedError,


ConnectionRefusedError et ConnectionResetError.

exception BrokenPipeError

Une sous-classe de ConnectionError, levé en essayant d'écrire sur un pipe


alors que l'autre extrémité a été fermée, ou en essayant d'écrire sur un
connecteur (socket en anglais) qui a été fermé pour l'écriture. Correspond
à errno EPIPE et ESHUTDOWN.

exception ConnectionAbortedError

Une sous-classe de ConnectionError, levée lorsqu'une tentative de


connexion est interrompue par le pair. Correspond à errno
ECONNABORTED.

exception ConnectionRefusedError

Une sous-classe de ConnectionError, levée lorsqu'une tentative de


connexion est refusée par le pair. Correspond à errno ECONNREFUSED.

exception ConnectionResetError
183
PYTHON

Une sous-classe de ConnectionError, levée lorsqu'une connexion est


réinitialisée par le pair. Correspond à errno ECONNRESET.

exception FileExistsError

Levée en essayant de créer un fichier ou un répertoire qui existe déjà.


Correspond à errno EEXIST.

exception FileNotFoundError

Levée lorsqu'un fichier ou répertoire est demandé mais n'existe pas.


Correspond à errno ENOENT.

exception InterruptedError

Levée lorsqu'un appel système est interrompu par un signal entrant.


Correspond à errno EINTR.

Modifié dans la version 3.5: Python relance maintenant les appels système
lorsqu'ils sont interrompus par un signal, sauf si le gestionnaire de signal
lève une exception (voir PEP 475 pour les raisons), au lieu de lever
InterruptedError.

exception IsADirectoryError

Levée lorsqu'une opération sur un fichier (comme os.remove()) est


demandée sur un répertoire. Correspond à errno EISDIR.

exception NotADirectoryError

Levée lorsqu'une opération sur un répertoire (comme os.listdir()) est


demandée sur autre chose qu'un répertoire. Correspond à errno
ENOTDIR.

exception PermissionError

Levée lorsqu'on essaye d'exécuter une opération sans les droits d'accès
adéquats — par exemple les permissions du système de fichiers.
Correspond à errno EACCES et EPERM.

exception ProcessLookupError

Levée lorsqu'un processus donné n'existe pas. Correspond à errno


ESRCH.
184
PYTHON

exception TimeoutError

Levée lorsqu'une fonction système a expiré au niveau système.


Correspond à errno ETIMEDOUT.

Nouveau dans la version 3.3: Toutes les sous-classes d'OSError ci-dessus ont été
ajoutées.

Voir aussi

PEP 3151 -- Refonte de la hiérarchie des exceptions système et IO

7.1.7 Avertissements

Les exceptions suivantes sont utilisées comme catégories d'avertissement ; voir


warning-categories pour plus d'informations.

exception Warning

Classe de base pour les catégories d'avertissement.

exception UserWarning

Classe de base pour les avertissements générés par du code utilisateur.

exception DeprecationWarning

Classe de base pour les avertissements sur les fonctionnalités obsolètes,


lorsque ces avertissements sont destinés aux autres développeurs Python.

exception PendingDeprecationWarning

Classe de base pour les avertissements d'obsolescence programmée. Ils


indiquent que la fonctionnalité peut encore être utilisée actuellement, mais
qu'elle sera supprimée dans le futur.

Cette classe est rarement utilisée car émettre un avertissement à propos


d’une obsolescence à venir est inhabituel, et DeprecationWarning est
préféré pour les obsolescences actuelles.

exception SyntaxWarning

Classe de base pour les avertissements sur de la syntaxe douteuse.


185
PYTHON

exception RuntimeWarning

Classe de base pour les avertissements sur les comportements d'exécution


douteux.

exception FutureWarning

Classe de base pour les avertissements à propos de fonctionnalités qui


seront obsolètes dans le futur quand ces avertissements destinés aux
utilisateurs finaux des applications écrites en Python.

exception ImportWarning

Classe de base pour les avertissements sur des erreurs probables dans les
importations de modules.

exception UnicodeWarning

Classe de base pour les avertissements liés à l'Unicode.

exception BytesWarning

Classe de base pour les avertissements liés à bytes et bytearray.

exception ResourceWarning

Classe de base pour les avertissements liés à l'utilisation de ressources.


Ignorée par les filtres d’avertissements par défaut.

Nouveau dans la version 3.2.

7.1.8 Hiérarchie des exceptions

La hiérarchie de classes pour les exceptions natives est la suivante :

BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
186
PYTHON

| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
| +-- ModuleNotFoundError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
187
PYTHON

| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning

7.2. Gérer les exceptions en Python avec try, except, else et finally
Python nous fournit des structures permettant de gérer manuellement certaines
exceptions. Nous allons voir comment mettre en place ces structures dans cette
leçon.

7.2.1 L’instruction try… except

Les clauses try et except fonctionnent ensemble. Elles permettent de tester (try)
un code qui peut potentiellement poser problème et de définir les actions à
prendre si une exception est effectivement rencontrée (except).

Imaginons par exemple un script qui demande à un utilisateur d’envoyer deux


nombres grâce à la fonction input() qui permet de recevoir des données
d’utilisateurs externes.

Le but de notre script va être de calculer le quotient de ces deux nombres entiers.
Ici, on peut déjà anticiper des cas d’erreurs qui peuvent se présenter :
l’utilisateur peut nous envoyer autre chose qu’un nombre entier ou peut nous
envoyer un dénominateur égal à 0, ce qui est interdit en mathématique.

On va vouloir gérer ces deux cas exceptionnels. Pour cela, on va pouvoir utiliser
deux blocs try et except comme cela :
188
PYTHON

Ici, on place le code à tester à l’intérieur du bloc try. Si aucune erreur n’est
détectée par Python lors de l’exécution du code, c’est-à-dire si aucun objet
exception n’est créé, ce qui se situe dans la clause except va être ignoré.
189
PYTHON

En revanche, si une exception intervient pendant l’exécution du code dans try, le


reste du code dans cette clause est ignoré et on rentre dans l’instruction except.
Gérer les exceptions comme cela permet notamment d’éviter l’arrêt de
l’exécution du script dans des cas où cela ne nous semble pas nécessaire.

Notre code ci-dessus est cependant loin d’être optimise car notre clause except
est bien trop large. Lorsqu’on gère les exceptions manuellement, on voudra
toujours apporter la gestion la plus fine possible pour éviter de capturer toutes
les erreurs n’importe comment.

Pour cela, nous allons préciser le type d’erreur qu’une instruction except doit
intercepter. Si on souhaite gérer plusieurs types d’exceptions, on pourra préciser
autant d’instructions except qu’on le souhaite à la suite d’un try.

Regardez plutôt le code ci-dessous :


190
PYTHON
191
PYTHON

Ce code est déjà beaucoup plus optimisé puisqu’il nous permet une gestion plus
fine des erreurs et ne va en l’occurence capturer que deux types d’exceptions : le
cas où les données entrées ne sont pas des entiers et le cas où le dénominateur
est égal à 0.

Ce code demande cependant bien évidemment de connaitre les classes


d’exception Python, mais il suffit de consulter la documentation en cas de doute.

Notez que rien ne nous empêche de préciser un except sans classe à la fin si on
souhaite absolument donner des ordres dans le cas où Python capturerait tout
autre type d’exceptions que ceux correspondant aux clauses except précédentes.

7.2.2 La clause else

Nous allons également pouvoir ajouter une clause else en fin d’instruction try…
except. Le code contenu dans cette clause sera exécuté dans le cas où aucune
exception n’a été levée par la clause try.

Il est considéré comme une bonne pratique de placer le code “non


problématique” dans la clause else plutôt que dans la clause try.

On pourrait ainsi réécrire notre exemple précédent de la façon suivante :


192
PYTHON
193
PYTHON

7.2.3 La clause finally

La dernière clause à connaitre est la clause fin ally. Le code qu’elle contient sera
exécuté dans tous les cas, qu’une exception ait été levée par la clause try ou pas.

Cette clause va s’avérer très utile lorsqu’on voudra terminer certaines opérations
(fermer un fichier par exemple) quel que soit l’état du script.

7.2.4 Définir nos propres classes d’exception


194
PYTHON

Pour finir, vous devez savoir que Python nous laisse la possibilité de créer nos
propres classes d’exception.

Pour cela, nous allons toujours créer des classes à partir de la classe de base
Exception.

Définir nos propres exceptions va s’avérer être une fonctionnalité très utile
notamment dans le cas où on souhaite distribuer un module Python et que
certaines de nos fonctions peuvent déclencher des exceptions non prises en
charge par les classes d’exception standard Python.

CONCLUSION DU COURS PYTHON


Python est un langage qui a été créé avec l’objectif d’être facilement
compréhensible. Pour cette raison, et pour la structure du langage en général qui
pousse les développeurs à coder plus proprement et à adopter de bonne
pratiques, il est l’un des langages les plus recommandés aux personnes
souhaitant s’initier à la programmation.

Si Python est simple à apprendre, il n’en est pas moins puissant et versatile : ce
langage peut être utilisé pour effectuer des tâches complexes et pour mener à
bien différents projets très différents, que ce soit la création d’applications Web
ou de programmes divers.

Dans ce cours, nous avons passé en revue les éléments du langage Python à
connaitre : variables, structures de contrôle, fonctions, l’orienté objet, la prise en
charge des erreurs, l’intégration de modules et la manipulation de fichiers.

Avec un peu d’imagination, ces éléments vont vous permettre de créer des
projets déjà relativement complexes.

J’ai volontairement laissé de côté la partie « utilisation de Python pour le Web »


de côté car sur ce sujet il est selon moi préférable d’utiliser l’excellent
framework Python Django qui nous permet de créer des structures Web
complexes et robustes relativement simplement et très rapidement.

Vous aimerez peut-être aussi