0% ont trouvé ce document utile (0 vote)
8 vues119 pages

Cours Python

Ce document est un cours sur la programmation en Python, destiné aux débutants. Il couvre les bases du langage, y compris l'installation, l'utilisation de la ligne de commande, et les concepts fondamentaux tels que les instructions, les expressions, et les variables. Le cours est structuré en chapitres, chacun abordant des sujets spécifiques pour faciliter l'apprentissage progressif.

Transféré par

othman ib
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 PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
8 vues119 pages

Cours Python

Ce document est un cours sur la programmation en Python, destiné aux débutants. Il couvre les bases du langage, y compris l'installation, l'utilisation de la ligne de commande, et les concepts fondamentaux tels que les instructions, les expressions, et les variables. Le cours est structuré en chapitres, chacun abordant des sujets spécifiques pour faciliter l'apprentissage progressif.

Transféré par

othman ib
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 PDF, TXT ou lisez en ligne sur Scribd

Programmation en Python

Dimitri Merejkowsky - Contenu placé sous licence CC BY 4.0

sept. 01, 2025


Table des matières :

1 Chapitre 1 - Introduction 3

2 Chapitre 2 - Premiers pas 5

3 Chapitre 3 - Instructions, expressions, variables et types 11

4 Chapitre 4 - Contrôle de flux 19

5 Chapitre 5 - Introduction aux fonctions 25

6 Chapitre 6 - Listes 31

7 Chapitre 7 - None et pass 39

8 Chapitre 8 - Dictionnaires 43

9 Chapitre 9 - Tuples 49

10 Chapitre 10 - Introduction aux classes 53

11 Chapitre 11 - Introduction aux modules 61

12 Chapitre 12 - Couplage et composition 65

13 Chapitre 13 - Bibliothèques 69

14 Chapitre 14 - Données binaires et fichiers 79

15 Chapitre 15 - Linterpréteur interactif 89

16 Chapitre 16 - Héritage 93

17 Chapitre 17 - Décorateurs 99

18 Chapitre 18 - Exceptions 105

19 Chapitre 19 - Objets 111

i
ii
Programmation en Python

Ce cours est destiné à toute personne qui voudrait découvrir la programmation en général et le langage Python en
particulier - il est également disponible en pdf à ladresse : [Link]
Le pdf comme le site sont régulièrement mis à jour, et les sources sont disponibles publiquement sur sourcehut.
Jespère quil vous plaira ! Sinon, nhésitez pas à vous rendre sur ma page de contact pour me faire part de vos remarques.
Enfin, notez que ce cours est placé sous licence CC BY 4.0, ce qui signifie que vous pouvez le partager et le modifier
comme bon vous semble, à la seule condition de me créditer de façon appropriée.
Bonne lecture !

Table des matières : 1


Programmation en Python

2 Table des matières :


CHAPITRE 1

Chapitre 1 - Introduction

1.1 Objet de ce cours

Apprendre la programmation en partant de rien, en utilisant Python et la ligne de commande.

1.1.1 Pourquoi Python ?

— Excellent langage pour débuter - il a dailleurs été créé avec cet objectif en tête.
— Mon langage préféré.
— Facile à installer quelque soit le système dexploitation (Linux, macOS, Windows).

1.1.2 Pourquoi la ligne de commande ?

Cest une interface universelle. Pour faire des programmes en lignes de commande, on a juste besoin de manipuler du
texte, et cest le plus simple au début.

1.1.3 Comment utiliser ce cours

Il est important de noter que les chapitres sont prévus pour être lus dans lordre.
Par exemple, pour bien comprendre le chapitre 10 sur les classes, il faut avoir bien compris les chapitres précédents,
car les explications du chapitre 10 supposent que les notions introduises aux chapitres 1 à 9 sont acquises !
Il est en conséquence recommandé darriver à résoudre les exercices en fin de chapitre avant de passer au suivant.

3
Programmation en Python

1.2 Présentation du langage Python

1.2.1 Utilisation de Python

— Aussi appelé ńălangage de scriptăż, glue language.


— Bon partout, excellent nulle part.
— Exemples dutilisation :
— sciences (physique, chimie, linguistique ) ;
— animation (Pixar, Disney ) ;
— sites web (journaux, youtube, ) ;
— ligne de commande ;

1.2.2 Petit détour : version dun programme

— Comme les versions dun document.


— Si le nombre est plus grand, cest plus récent.
— Souvent en plusieurs morceaux : 1.3, 1.4, 3.2.5. etc.
— Plus lécart est grand, plus le programme a changé.
— 3.2.5 -> 3.2.6 : pas grand-chose ;
— 1.5.1 -> 4.3 : beaucoup de changements ;
— On omet souvent le reste des chiffres quand ce nest pas nécessaire.

1.2.3 Historique

— Créé par Guido van Rossum. Conçu à la base pour lenseignement.


— Le nom vient des Monty Python (si, si).
— Python 1 : Sortie en 1991.
— Python 2 : en 2000.
— Python 3 : en 2008.

1.2.4 Le grand schisme

La plupart des langages continuent à être compatibles dune version à lautre.


Ce nest pas le cas pour Python3, et cela a causé beaucoup de confusion et de débats.
Heureusement, 10 ans plus tard, la situation sest arrangée, et Python2 a cessé dêtre maintenu le premier janvier 2020.

1.2.5 Python3

Ce cours fonctionne donc uniquement avec Python3.


Nutilisez pas Python2, sinon certaines choses expliquées ici ne fonctionneront pas :/

4 Chapitre 1. Chapitre 1 - Introduction


CHAPITRE 2

Chapitre 2 - Premiers pas

2.1 La ligne de commande

2.1.1 Pourquoi la ligne de commande ?

— Très puissant.
— Ancien, mais toujours dactualité.
— Indispensable dans de nombreux cas.
— Écrire des programmes qui fonctionnent dans la ligne de commande est (relativement) simple.
— Possibilités infines, même si on ne fait que manipuler du texte.

2.1.2 Les bases

Les lignes de commandes sont à taper dans un terminal.


— Sur linux, vous en avez probablement un dinstallé par défaut.
— Sur macOS, il se trouve dans Applications/Utilitaires.
— Sur Windows, il se lance en tapant [Link].
Dans tous les cas, cela ressemble à ceci :

Notez le petit bout de texte avant le curseur : on appelle ça une invite de commande (prompt en anglais).
Pour lancer une commande, on tape son nom, suivi parfois dun certain nombre de mots séparés par des espaces, puis
on appuie sur entrée.
Par exemple, on peut utiliser ls (ou dir sous Windows) pour lister le contenu du répertoire courant :

5
Programmation en Python

Et on peut utiliser cd suivi du nom dun répertoire pour changer de répertoire courant :

Notez que linvite de commande a changé.

2.2 Installation

Pour suivre ce cours, il vous faudra installer deux composants essentiels :


— linterpréteur Python ;
— un éditeur de texte.

2.2.1 Installation de Python

Linux

Il y a toutes les chances que Python soit déjà installé sur votre distribution. Pour vous en assurer, tapez :

python3 --version

Sinon, installez le paquet correspondant à Python3 (quelque chose comme sudo apt install python3)

macOS

Python3 est disponible dans homebrew.

brew install python

Windows

Python3 est disponible dans Microsoft Store.


Sinon, vous pouvez aussi télécharger linstalleur depuis [Link]
Veillez à cocher la case ńăAjouter Python au PATHăż.

6 Chapitre 2. Chapitre 2 - Premiers pas


Programmation en Python

2.2.2 Installation dun éditeur de texte

Je vous conseille pour commencer dutiliser un éditeur de texte basique. Vous navez pas besoin dun IDE, surtout si vous
débutez
— Linux ; gedit, kate, ;
— macOS : CotEditor ;
— Windows : Notepad++.
Jinsiste sur simple. Inutile dinstaller un IDE pour le moment.

2.2.3 Configuration de léditeur de texte

Prenez le temps de configurer votre éditeur de texte de la façon suivante :


— police de caractères à chasse fixe ;
— indentation de 4 espaces ;
— remplacer les tabulations par des espaces ;
— activer la coloration syntaxique.
Cela vous évitera des soucis plus tard.

2.3 Code source

2.3.1 Définition

Aussi appelé : ńăcode sourceăż, ou ńăsourceăż.


Lessence du logiciel libre :)

2.3.2 Notre premier fichier source

Insérez le code suivant dans votre éditeur de texte :

print("Bonjour, monde")
# affiche: Bonjour, monde

Oui, juste ces deux lignes.


Sauvegardez dans un fichier [Link] dans Documents/python par exemple.

2.3.3 Lancer du code en ligne de commande

Lancez une invite de commandes et tapez quelque chose comme :

cd Documents/python/
python3 [Link]

(Utilisez python sous Windows)


Si tout se passe bien, vous devrez voir safficher ceci :

Bonjour, monde

Vous savez maintenant comment exécuter du code Python dans nimporte quel fichier :

2.3. Code source 7


Programmation en Python

1. Écrire le code dans un fichier ;


2. Se rendre dans le répertoire contenant le fichier et lancer python3 (ou python) suivi du nom du fichier.

2.3.4 print()

Revenons sur ce quil sest passé : nous avions le mot print avec des parenthèses et quelque chose à lintérieur des
parenthèses, et ceci a provoqué laffichage du contenu des parenthèses dans le terminal.

2.3.5 Commentaires

La deuxième ligne, quant à elle, a été complètement ignorée par linterpréteur parce quelle commençait par un #. Il
sagit dun commentaire, et il sert principalement aux humains qui lisent le code.

2.3.6 Note à propos des exemples

La plupart des exemples de ce cours contiendront un ou plusieurs appels à print afin dafficher les opérations que
linterpréteur a effectué.
Pour lire ce cours de manière efficace, il est conseillé de lancer les exemples de code sur votre machine, et de vérifier
si ce qui est affiché sur votre machine correspond à ce qui est écrit dans le cours.
Il est aussi recommandé de ne pas copier/coller le code.
À la place, prenez le temps de retaper le code dans votre éditeur.
Plusieurs raisons à cela :
— Recopier le code vous aidera à vous souvenir de la syntaxe
— Si vous faites des erreurs, Python vous préviendra et vous découvrirez les erreurs courantes
— Il est possible que des erreurs subsistent dans ce cours, et procéder ainsi nous permettra de les corriger.

2.4 Maths simples

2.4.1 Opérations avec des entiers

On peut utiliser +, *, - avec des entiers :

print(1 + 2)
# affiche: 3

print(6 - 3)
# affiche: 3

print(2 * 4) # une étoile pour la multiplication


# affiche: 8

print(3 ** 2) # deux étoiles pour l'opération 'puissance'


# affiche: 9

8 Chapitre 2. Chapitre 2 - Premiers pas


Programmation en Python

2.4.2 Opérations avec des flottants

Cest le . qui fait le flottant.

print(0.5 + 0.2)
# affiche: 0.7

On utilise / pour les divisions flottantes :

print(10 / 2)
# affiche: 5.0 (et non '5')

Notez que les flottants sont imprécis, ce qui explique le 5 à la fin de laffichage de la division de 10 par 3 :

print(10 / 3)
# affiche:3.3333333333333335

2.4.3 Division entières et modulo

14 divisé par 3 font 4 avec un reste de 2.


On peut récupérer le quotient avec // et le reste avec %.

print(14 // 3)
# affiche: 4

print(14 % 3)
# affiche: 2

Avertissement : Le % na rien à voir avec un pourcentage !

2.4.4 Priorité des opérations

Comme en maths, la multiplication est prioritaire sur les autres opérations :

print(1 + 2 * 3)
# affiche: 7

et on peut utiliser des parenthèses pour grouper les opérations :

print((1 + 2) * 3)
# affiche: 9

2.4. Maths simples 9


Programmation en Python

10 Chapitre 2. Chapitre 2 - Premiers pas


CHAPITRE 3

Chapitre 3 - Instructions, expressions, variables et types

3.1 Expressions, instructions, et variables

3.1.1 Instructions

Pour linstant, dans tous les exemples de code, chaque ligne quon a écrit contenait une instruction.
Un instruction a un effet sur le programme dans lequel elle est présente.
Par exemple, linstruction print("bonjour") affiche ńăbonjourăż dans le terminal. On dit que linstruction est exécu-
tée.
En règle générale, les instructions sont exécutées une par une, de haut en bas.

3.1.2 Expressions

Les instructions peuvent contenir des expressions.


Un expression est toujours évaluée pour retourner une valeur.
Par exemple, 1 + 2 est une expression qui renvoie la valeur 3 une fois évaluée.
Elle est constituée de 3 éléments :
— le littéral 1 ;
— lopérateur + ;
— le littéral 2.
Pour évaluer une expression, Python remplace les littéraux par leur valeur, puis calcule la valeur finale en utilisant les
opérateurs.
Notez que les expressions peuvent être imbriquées :

1 + (2 * 3)

11
Programmation en Python

À droite du plus, on a une expression 2 + 3. Quand Python évaluera lexpression, il verra dabord le littéral 1 et le +,
puis il évaluera lexpression à droite (2 * 3 = 6), et finalement lexpression en entier (1 + 6 = 7).
Notez que si vous écrivez une ligne contenant une expression, elle est évaluée mais rien nest exécuté :

print("Bonjour")
40 + 2
print("Au revoir")
# Affiche: 'Bonjour' puis 'Au revoir'

Ici lexpression 40 + 2 a été évaluée, mais Python na rien fait avec le résulat, il est simplement passé à linstruction
suivante.

3.1.3 Variables et valeurs

On peut associer des variables à des valeurs en les plaçant de part et dautre du signe = : on appelle cette opération une
assignation :

a = 2

Ici on assigne lentier 2 à la variable a.


Notez quune assignation nest pas une expression, cest une instruction.
Si plus tard dans le code, on utilise le nom de la variable, tout se passera comme si le nom de la variable avait été
remplacé par sa valeur :

a = 2
print(a)
# affiche: 2

3.1.4 Variables et expressions

En fait, on peut assigner nimporte quelle expression à une variable, et pas simplement des littéraux :

a = 1 + 2
print(a)
# affiche: 3

3.1.5 Variables et expressions contenant dautres variables

Les expressions peuvent également contenir des variables.


Quand Python évalue une expression qui contient des noms de variables, il remplace celles-ci par leur valeur :

a = 1
print(a + 2) # ici "a" a été remplacé par 1
# affiche: 3

Notez que la valeur de la variable a na pas changé :

12 Chapitre 3. Chapitre 3 - Instructions, expressions, variables et types


Programmation en Python

a = 1
print(a + 2)
# affiche: 3
print(a)
# affiche: 1

Autres exemples :

x = 1
y = 2
print(x+y) # ici x a été remplacé par 1 et y par 2
# affiche: 3

3.1.6 Changer la valeur dune variable

On peut aussi changer la valeur dune variable en assignant une nouvelle valeur à celle-ci :

a = 2
print(a)
a = 3
print(a)
# affiche: 2, puis 3

3.1.7 Combiner opération et assignation

La notation += permet de combiner addition et assignation : les deux exemples ci-dessous sont équivalents :

x = 3
x = x + 1

x = 3
x += 1

Cela fonctionne aussi pour -=, /=, etc.

3.1.8 Nom des variables

Ci-dessus jai utilisé des noms de variables à une lettre, mais il est préférable davoir des noms longs et descriptifs.
Aussi, la convention est de :
— les écrire en minuscules ;
— de séparer les mots par des tirets bas (underscore) :

score = 42
âge_moyen = 22
On dit quon utilise le snake case (parce que ça ressemble vaguement à un serpent)
Notez que certains mots ne peuvent pas être utilisés comme nom de variables. On les appelle des mots-clés. La liste est
disponible ici : [Link]

3.1. Expressions, instructions, et variables 13


Programmation en Python

3.2 Chaînes de caractères

Les chaînes de caractères, aussi appelées ńăstringsăż, permettent de représenter du texte. On a utilisé une string pour
afficher ńăbonjour mondeăż dans le chapitre précédent.
On écrit toujours les strings entre guillemets (ou quotes).
soit avec des doubles guillemets :

print("Bonjour monde!")
# affiche: Bonjour monde!

soit avec des guillemets simples :

print('Bonjour monde!')
# affiche: Bonjour monde!

3.2.1 Double et simple quotes

On peut mettre des simples quotes dans des double quotes et vice-versa :

print("Il a dit: 'bonjour' ce matin.")


# affiche: Il a dit: 'bonjour' ce matin.

print('Il a dit: "bonjour" ce matin')


# affiche: Il a dit: "bonjour" ce matin

3.2.2 Échappement

On peut aussi échapper des caractères avec la barre oblique inversée \\ - backslash.

print('Il a dit: "bonjour". C\'est sympa!')


# affiche: Il a dit: "bonjour". C'est sympa!

3.2.3 Concaténation

On peut construire de longues chaînes de caractères en en concaténatant de plus petites, avec lopérateur + :

name = "John"
message = "Bonjour " + name + " !"
print(message)
# affiche: Bonjour John !

14 Chapitre 3. Chapitre 3 - Instructions, expressions, variables et types


Programmation en Python

3.2.4 Répétition

On peut construire une longue string en répétant la même petite string plusieurs fois avec lopérateur * :

message = "Na" * 3
print(message)
# affiche: NaNaNa

3.3 Types

On a vu quon pouvait utiliser + à la fois pour additionner des nombres ou concaténer des strings. Mais on ne peut pas
utiliser + avec une string dun côté et un entier de lautre :

a = 42
b = 4
c = a + b # ok

salutation = "bonjour, "


prénom = "Bob"
salutation + prénom # ok

résultat = a + prénom
# affiche:
# TypeError: can only concatenate str (not "int") to str

Ceci est notre premier message derreur : si linterpréteur est incapable dexécuter une instruction, il affiche un message
derreur et sinterrompt immédiatement.

3.3.1 Conversions

Pour résoudre le problème ci-dessus, il faut effectuer une conversion de types :

Entier vers string

On peut convertir un entier en string en utilisant le mot str et des parenthèses autour de lexpression :

x = 40
y = 2
message = "La réponse est: " + str(x + y)
print(message)
# affiche: La réponse est 42

3.3. Types 15
Programmation en Python

String vers nombres

Inversement, on peut convertir un string en entier en utilisant le mot int et des parenthèses :

quarante_en_chiffres = "40"
réponse = int(quarante_en_chiffres) + 2
print(réponse)
# affiche: 42

Pour convertir une string en flottant, on peut utiliser float() :

taille_sur_le_passeport = "1.62"
taille_en_mètres = float(taille_sur_le_passeport)

3.4 Booléens

On appelle booléenne une valeur qui peut être soit vraie, soit fausse.
En Python, les littéraux True et False représentent respectivement les valeurs vraies et fausses.
(Notez quils commencent par une majuscule)

3.4.1 Comparaisons

Certaines expressions renvoient des booléens, cest à dire soit la valeur True, soit la valeur False

== égal
!= différent
> strictement supérieur
>= supérieur ou égal
< strictement inférieur
<= inférieur ou égal

Par exemple :

a = 2
b = 3
print(a > b)
# affiche: False

print(2 + 2 == 4)
# affiche: True

Avertissement : Ne pas confondre == pour la comparaison et = pour lassignation

Notez que deux valeurs avec des types différents sont en général considérés comme différents :

1 == "1" # False

Cette règle admet des exceptions, par exemple un flottant peut être égal à un entier :

16 Chapitre 3. Chapitre 3 - Instructions, expressions, variables et types


Programmation en Python

1 == 1.0 # True

3.4.2 Autres opérations booléennes

not négation
and et
or ou

Exemples :

a = not True
print(a)
# affiche `False`

il_pleut = True
j_ai_un_parapluie = False
print(il_pleut and j_ai_un_parapluie)
# affiche: False

je_suis_mouillé = il_pleut and not j_ai_un_parapluie


print(je_suis_mouillé)
# affiche: True

3.4. Booléens 17
Programmation en Python

18 Chapitre 3. Chapitre 3 - Instructions, expressions, variables et types


CHAPITRE 4

Chapitre 4 - Contrôle de flux

4.1 Contrôle de flux

Pour linstant, toutes les instructions que nous avons écrites ont été exécutée une par une et dans lordre dapparition dans
le code source.
De plus, chaque ligne était constituée dune unique expression.
Modifier lordre dexécution de ces instructions sappelle le contrôle de flux, et cest lessence même de la programmation !

4.1.1 if

On peut utiliser le mot-clé if pour autoriser ou empêcher lexécution des instructions suivantes :

a = 3
b = 4
if a == b:
print("a et b sont égaux")
# n'affiche rien

La 4ème ligne nest pas exécutée parce la condition est fausse.


Notes :
— il y a le caractère : (deux points) à la fin de la ligne ;
— le code en-dessous du if commence par 4 espaces : on appelle cela une indentation.
Notez quon a utilisé une expression après le if. On ne peut pas utiliser dinstruction après un if en Python.
Autrement dit, ce code ne fonctionne pas :

if a = 3:
print("a égale 3")
# affiche: SyntaxError

On parle aussi de ńăblocăż si plusieurs lignes sont indentées :

19
Programmation en Python

a = 3
b = 4
if a == b:
# début du bloc
print("a et b sont égaux")
c = 2 * a
# fin du bloc

Notez quon reprend lordre habituel dexécution des instructions sil y a un bloc indenté dans lautre sens après le if :

a = 3
b = 4
if a == b:
# début du bloc
print("a et b sont égaux")
c = 2 * a
# fin du bloc
# on est après le bloc if
print("on continue")

Ce code naffiche pas ńăa et b sont égauxăż, mais affiche bien ńăon continueăż.

if / else

On peut utiliser le mot-clé else après un condition en if pour exécuter un bloc si la condition est fausse :

a = 3
b = 4
if a == b:
print("a et b sont égaux")
else:
print("a et b sont différent")
# affiche: a et b sont différents

if / elif

On peut utiliser if, elif et else pour enchaîner plusieurs conditions :

age = 23
if age < 10:
print("âge inférieur à dix")
elif 10 <= age < 20:
print("âge entre 10 et 20")
elif 20 <= age < 40:
print("âge entre 20 et 40")
else:
print("âge supérieur à 40")
# affiche: âge entre 20 et 40

20 Chapitre 4. Chapitre 4 - Contrôle de flux


Programmation en Python

while

On peut utiliser le mot-clé while pour répéter un bloc tant quune condition est vraie :

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

0
1
2

Notez que la variable i passe par plusieurs valeurs différentes.


Le fait de répéter un bloc plusieurs fois est souvent appelée une boucle.

Boucle infinie

On parle de boucle infinie si la condition ne devient jamais fausse :

while True:
print("spam!")

Dans ce cas, il faut appuyer sur CTRL-C pour interrompre le programme.

Combiner while, if, et break

On peut ńăsortirăż de la boucle while avec le mot-clé break :

i = 0
while True:
i = i + 1
print(i)
if i > 3:
break

1
2
3
4

4.2 Falsy et truthy

4.2.1 Expressions après un if

Jusquici les expressions quon a utilisé donnait un booléen une fois évaluées, mais une expression après un if peut être
dun autre type.
Par exemple, un entier :

4.2. Falsy et truthy 21


Programmation en Python

x = 0
if x:
print("x n'est pas nul")
else:
print("x est nul")

# affiche: x est nul

On dit que 0 est Falsy, parce quaprès un if, il se comporte comme une expression qui vaudrait False.
Réciproquement, tous les entiers sauf 0 sont Truthy, parce quils se comportent comme une expression qui vaudrait
True :

y = 6
if y:
print("y n'est pas nul")
else:
print("y est nul")

# affiche: y n'est pas nul

On retrouve ce principe avec les chaînes de caractères :

message = ""
if message:
print("le message n'est pas vide")
else:
print("le message est vide")
# affiche: le message est vide

Les chaînes vides sont falsy, les autres sont truthy.

4.2.2 Expressions quelconques

En fait, on peut utiliser tous les opérateurs booléens avec des expressions quelconques :

message = ""
if not message:
print("le message est vide")
# affiche: le message est vide

score = 42
message = "pas un message vide"
if message and score:
print("le message et le score sont truthy")
# affiche: le message et le score sont truthy

22 Chapitre 4. Chapitre 4 - Contrôle de flux


Programmation en Python

4.3 Exercice

Ceci étant le premier exercice du cours, il mérite quelques explications.


Chaque exercice comporte une suite de consignes, et quelques indices.
À vous ensuite décrire le code qui correspond aux consignes.

4.3.1 Consignes

Il vous faut implémenter le programme suivant :


1. Tirer un nombre au hasard entre 1 et 100 (appelons-le le nombre_secret).
2. Démarrer une boucle.
3. À chaque étape :
— afficher ńăDevine le nombre secretăż ;
— bloquer le programme jusquà ce que lutilisateur entre un nombre et appuie sur entrée (appelons-le
entrée_utilisateur) ;
— si lentrée utilisateur est plus grande que le nombre secret, afficher ńătrop grandăż ;
— si lentrée utilisateur est plus petite que le nombre secret, afficher ńătrop petităż ;
— si lentrée utilisateur est égale au nombre secret, afficher ńăgagné !ăż et quitter la boucle.

4.3.2 Indices

Lire une entrée utilisateur

Pour bloquer le programme et lire une entrée utilisateur, vous pouvez utiliser la ligne suivante :

entrée_utilisateur = input()

Cette instruction va :
— interrompre le script ;
— lire ce que lutilisateur tape jusquà ce quil tape ńăentréeăż ;
— et assigner la valeur correspondante à la variable entrée_utilisateur.

Tirer un nombre au hasard

Pour tirer un nombre au hasard entre 1 et 100, vous pouvez utiliser les deux lignes suivantes :

import random
nombre_secret = [Link](0, 100)

À la fin de ces deux instructions, une valeur entre 1 et 100 tirée au hasard sera assignée à la variable nombre_secret.

4.3. Exercice 23
Programmation en Python

4.3.3 Squelette

Pour commencer, copier le code suivant dans un fichier (par exemple, [Link])

import random

nombre_secret = [Link](0, 100)

print("devine le nombre auquel je pense entre 0 et 100")


entrée_utilisateur = int(input())

while True:
if entrée_utilisateur == nombre_secret:
print("bravo")
break
else:
print("mauvaise réponse")
entrée_utilisateur = int(input())

Si vous lancez python3 [Link] vous constaterez que le jeu est très difficile parce que le programme affiche
simplement ńămauvaise réponseăż en boucle jusquà ce que lutilisateur devine le nombre secret.
Votre but est de modifier le code pour implémenter correctement le programme, et ainsi rendre le jeu jouable :)

4.3.4 Obtenir de laide

Si vous lisez ceci en dehors dun cours et que vous êtes coincés, nhésitez pas à me contacter.
Bon courage !

24 Chapitre 4. Chapitre 4 - Contrôle de flux


CHAPITRE 5

Chapitre 5 - Introduction aux fonctions

5.1 Fonctions

5.1.1 Fonctions sans argument

Définition :

def dire_bonjour():
print("Bonjour")

Notez quon utilise aussi le snake case pour les noms de fonctions, comme pour les noms de variables.
— avec le mot-clé def ;
— avec un : à la fin et un bloc indenté (appelé le corps de la fonction).
Appel :

dire_bonjour()

— avec le nom de la fonction et des parenthèses.


Exemple complet :

def dire_bonjour():
print("Bonjour")

dire_bonjour()
# Affiche: bonjour'

— le nom de la fonction est le mot utilisé pour la définir et lappeler ;


— le corps de la fonction est le bloc après le def() ;
— quand on définit une fonction, on associe un nom avec un corps ;
— quand on appelle une fonction, on exécute le corps.

25
Programmation en Python

5.1.2 Le pouvoir des fonctions

Ici on vient dajouter une nouvelle fonctionnalité à Python. Avant quon définisse la fonction dire_bonjour(), il ne savait
pas dire bonjour, il savait uniquement afficher des messages à lécran.
On dit quon a créé une abstraction. Et cest une technique extrêmement utile en programmation.

5.1.3 Fonction avec un argument

Définition, avec largument à lintérieur des parenthèses :

def dire_bonjour(prénom):
print("Bonjour " + prénom)

Appel, en passant une variable ou une valeur dans les parenthèses :

dire_bonjour("Germaine")

Pour évaluer une expression qui contient lappel a une fonction, on :


— assigne le contenu des parenthèses aux arguments de la fonction ;
— puis on éxécute les instructions dans le corps de la fonction.

# Ceci:
dire_bonjour("Dimitri")

# Est équivalent à cela:


prénom_de_dimitri = "Dimitri"
print("Bonjour " + prénom_de_dimitri)

# Lui-même équivalent à:
print("Bonjour " + "Dimitri")

Exemple complet :

def dire_bonjour(prénom):
print("Bonjour " + prénom)
dire_bonjour("Germaine")
# affiche: Bonjour Germaine

prénom_de_charlotte = "Charlotte"
dire_bonjour(prénom_de_charlotte)
# affiche: Bonjour Charlotte

5.2 Portée des variables

Les arguments dune fonction nexistent que dans le corps de celle-ci :

def dire_bonjour(prénom):
print("Bonjour " + prénom)

dire_bonjour("Dimitri") # Ok
print(prénom) # Erreur

26 Chapitre 5. Chapitre 5 - Introduction aux fonctions


Programmation en Python

Les variables définies en dehors du corps des fonctions sont disponibles partout :

salutation = "Bonjour "

def dire_bonjour(prénom):
print(salutation + prénom)

dire_bonjour("Dimitri")

Une variable peut avoir en ńăcacherăż une autre si elle a une portée différente :

prénom = "Dimitri" # portée: dans tout le programme

def dire_bonjour():
prénom = Max # portée: uniquement dans
# le corps dire_bonjour

print("Bonjour " + prénom)


# affiche: Bonjour Max

print("Bonjour " + prénom) j


# affiche: Bonjour Dimitri

5.3 Valeur de retour dune fonction

On peut également appeler une fonction dans une expression à droite dune assignation de variable.
Dans ce cas, la valeur de lexpression est obtenue en exécutant le corps de la fonction jusquà rencontrer linstruction
return et en évaluant lexpression à droite du return.
Par exemple :

def retourne_42():
return 42

x = retourne_42()
print(x)
# Affiche: 42

Ici, on peut dire que 42 est le résultat de lappel de la fonction retourne_42().


On peut utiliser if avec plusieurs return pour changer le résultat dune fonction :

def peut_conduire(âge):
if âge < 18:
return False
else:
return True

x = peut_conduire(16)
print(x)
# Affiche: False

5.3. Valeur de retour dune fonction 27


Programmation en Python

5.4 Fonctions à plusieurs arguments

On peut mettre autant darguments quon veut, séparés par des virgules :

def soustraction(x, y):


résultat = x - y
return résultat

résultat = soustraction(5, 4)
print(résultat)
# affiche: 1

5.4.1 Arguments nommés

En Python, on peut aussi utiliser le nom des arguments au lieu de leur position :

def dire_bonjour(prénom):
print("Bonjour " + prénom)

dire_bonjour(prénom="Gertrude")
# Affiche: Bonjour Gertrude

résultat = soustraction(y=4, x=5)


print(résultat)
# affiche: 1

5.5 Arguments par défaut

On peut aussi mettre des valeurs par défaut :

def dire_bonjour(prénom, enthousiaste=False):


message = "Bonjour " + prénom
if enthousiaste:
message += "!"
print(message)

Appel :

dire_bonjour("Thomas")
# affiche: Bonjour Thomas

dire_bonjour("Thomas", enthousiaste=True)
# affiche: Bonjour Thomas!

dire_bonjour("Thomas", enthousiaste=False)
# affiche: Bonjour Thomas

28 Chapitre 5. Chapitre 5 - Introduction aux fonctions


Programmation en Python

5.6 Fonctions natives

Fonctions qui sont toujours présentes dans linterpréteur. On en a déjà vu quelques unes :
— print(), input() : écrire et lire sur la ligne de commande ;
— str(), int() : convertir des entiers en strings et vice-versa.
Il y en a tout un tas !
La liste ici : [Link]

5.6.1 Retour sur print

On peut passer autant darguments quon veut à print() et :


— il les sépare par des espaces ;
— ajoute un retour à la ligne à la fin :

prénom = "Charlotte"
print("Bonjour", penom)
print("Ça va ?")

Bonjour Charlotte
Ça va ?

On peut demander à print() de changer son séparateur :

a = "chauve"
b = "souris"
print(a, b, sep="-")

chauve-souris

Ou de changer le caractère de fin :

print("Ceci tient", end="")


print("sur une seule ligne")

Ceci tient sur une seule ligne

5.7 Exercice

Le but de lexercice est dafficher un sapin de largeur arbitraire dans la console, comme ceci :

#
###
#####
#######
#########
#
#

5.6. Fonctions natives 29


Programmation en Python

Le sapin est composé dune suite de lignes, chacune des lignes étant constituée uniquement de dièses.
Il y a deux parties au sapin : les feuilles qui forment un triangle de largeur 1 tout en haut jusquà une ligne de largeur 9
tout en bas, et un pied constitué de deux dièses superposés

5.7.1 Indices

Pour construire une chaîne de caractères constituée uniquement de dièses vous pouvez utiliser lexpression suivante :

cinq_diéses = "#" * 5
print(cinq_diéses)

#####

5.7.2 Consignes

Partir du code suivant :

largeur = 9

def affiche_ligne(début, fin):


blancs_au_début = " " * début
largeur_ligne = fin - début
dièses = "#" * largeur_ligne
print(blancs_au_début + dièses)

def affiche_feuilles():
affiche_ligne(5, 6)
affiche_ligne(4, 7)
# à compléter

def affiche_pied():
affiche_ligne(5, 6)
# à compléter

def affiche_sapin():
affiche_feuilles()
affiche_pied()

affiche_sapin()

— Compléter le code pour afficher le sapin en entier.


— Remplacer tous les litéraux (5, 6, 4, 7) par des expressions utilisant la variable largeur.
— Demander à lutilisateur la largeur du sapin en début de programme au lieu dutiliser la valeur litérale 9. Vous
pouvez faire lhypothèse que la largeur est toujours un nombre impair.

30 Chapitre 5. Chapitre 5 - Introduction aux fonctions


CHAPITRE 6

Chapitre 6 - Listes

6.1 Principes fondamentaux

6.1.1 Définition

Une liste est une suite ordonnée déléments.

6.1.2 Créer une liste

Avec des crochets : [, ], et les éléments séparés par des virgules :

liste_vide = []
trois_entiers = [1, 2, 3]

6.1.3 Listes hétérogènes

On peut mettre des types différents dans la même liste :

ma_liste = [True, 2, "trois"]

On peut aussi mettre des listes dans des listes :

liste_de_listes = [[1, 2], ["Germaine", "Gertrude"]]

31
Programmation en Python

6.1.4 Connaître la taille dune liste

Avec len(), encore une fonction native :

liste_vide = []
taille = len(liste_vide)
print(taille)
# affiche: 0

trois_entiers = [1, 2, 3]
taille = len(trois_entiers)
print(taille)
# affiche: 3

6.1.5 Concaténation de listes

Avec + :

prénoms_1 = ["Alice", "Bob"]


prénoms_2 = ["Charlie", "Eve"]
prénoms = prénoms_1 + prénoms_2

print(prénoms)
# affiche: ['Alice', 'Bob', "Charlie", 'Eve']

On ne peut concaténer des listes quavec dautres listes :

scores = [1, 2, 3]
scores = scores + 4
# erreur

scores = [1, 2, 3]
scores = scores + [4]
print(scores)
# affiche: [1,2,3,4]

On peut aussi utiliser += pour combiner lassignation et la concaténation, comme avec les nombres :

a = 3
a += 2
print(a)
# Affiche: 5

x = [1, 2]
x += [3, 4, 5]
print(x)
# Affiche: [1, 2, 3, 4, 5]

32 Chapitre 6. Chapitre 6 - Listes


Programmation en Python

6.1.6 Indexer une liste

On peut récupérer un élément dune liste à partir de son index, en utilisant [i] où i est lindex de lélément.
Les index valides vont de 0 à n-1 où n est la taille de la liste :

fruits = ["pomme", "orange", "poire"]

print(fruits[0])
# affiche: "pomme"

print(fruits[1])
# affiche: "orange"

print(fruits[2])
# affiche: "poire"

fruits[3]
# erreur: IndexError

6.1.7 Modifier une liste

On peut modifier un élément dune liste en utilisant une assignation :

fruits = ["pomme", "orange", "poire"]


fruits[0] = "abricot"
print(fruits)
# affiche: ["abricot", "orange", "poire"]

6.2 Itération

6.2.1 Itérer sur les éléments dune liste

Avec les mots-clés for et in :

prénoms = ["Alice", "Bob", "Charlie"]


for prénom in prénoms:
# Chaque élément de la liste est assigné tour à tour
# à la variable 'prénom"
print("Bonjour", prénom)

Bonjour Alice
Bonjour Bob
Bonjour Charlie

6.2. Itération 33
Programmation en Python

6.2.2 break

Comme pour les boucles while, on peut interrompre la boucle for avec break :

prénoms = ["Alice", "Bob", "Charlie"]


for prénom in prénoms:
if prénom == "Bob":
break
print("Bonjour", prénom)

Bonjour Alice
Bonjour Bob

6.2.3 continue

On peut interrompre lexécution du bloc courant (et uniquement le bloc courant) avec le mot-clé continue :

prénoms = ["Alice", "Bob", "Charlie"]


for prénom in prénoms:
if prénom == "Bob":
continue
print("Bonjour", prénom)

Bonjour Alice
Bonjour Charlie

6.3 Listes et booléens

6.3.1 Falsy et truthy

Si on met une liste vide, if se comportera comme si on avait mis une valeur fausse, et si la liste nest pas vide , if se
comportera comme si on avait mis une valeur vraie :

ma_liste = [1, 2, 3]
if ma_liste:
print("ma_liste est truthy")
else:
print("ma_liste est falsy")
# affiche: ma_liste est truthy

mon_autre_liste = []
if mon_autre_liste:
print("mon_autre_liste n'est pas vide")
else:
print("mon_autre_liste est vide")
# affiche: mon_autre_liste est vide

On dit que les listes vides sont Falsy et les listes non-vides Truthy.

34 Chapitre 6. Chapitre 6 - Listes


Programmation en Python

6.3.2 Test dappartenance

On peut tester si un élément est dans une liste avec le mot-clé in :

prénoms = ["Alice", "Bob"]


print("Alice" in prénoms)
# affiche: True

prénoms = ["Alice", "Bob"]


print("Charlie" in prénoms)
# affiche: False

6.3.3 Comparaisons de listes

On peut utiliser lopérateur == avec deux listes de part et dautre. Les listes seront considérées comme égales si :
— elles ont la même taille ;
— tous leurs éléments sont égaux un à un en respectant lordre :

x = [1]
y = [1, 2]
print(x == y)
# affiche: False, x et y n'ont pas la même taille

x = [1, 2]
y = [1, 3]
print(x == y)
# affiche: False, x et y n'ont pas les mêmes éléments

x = [1, 2]
y = [2, 1]
print(x == y)
# affiche: False, x et y ont les mêmes éléments, mais
# pas dans le bon ordre

x = [1, 2]
y = [1]
y += [2]
print(x == y)
# affiche: True, x et y ont les mêmes éléments, dans le même ordre

6.4 Relation avec les strings

Les strings sont aussi des listes (presque).


On peut itérer sur les caractères dune string :

for c in "vache":
print(c)

6.4. Relation avec les strings 35


Programmation en Python

v
a
c
h
e

On peut tester si un caractère est présent :

print("e" in "vache")
# affiche: True

print("x" in "vache")
# affiche: False

Notez quon peut aussi utiliser in pour tester si une chaîne de caractères est contenue dans une autre :

print("ch" in "vache")
# affiche: True

On peut indexer une string :

prénom = "Charlotte"
l = prénom[0]
print(l)
# affiche: "C"

Mais on ne peut pas modifier une string en utilisant lindexation :

prénom = "Charlotte"
prénom[0] = "X"
# erreur: TypeError

6.5 Exercice

Le but de lexercice est dimplémenter le jeu du pendu.


Voila à quoi une session de jeu doit ressembler :

______
entrer une lettre
e
_____e
entrer une lettre
a
_a___e
entrer une lettre
u
_au__e
entrer une lettre
q
_au__e
entrer une lettre
(suite sur la page suivante)

36 Chapitre 6. Chapitre 6 - Listes


Programmation en Python

(suite de la page précédente)


c
_auc_e
entrer une lettre
h
_auche
entrer une lettre
g
gauche
Gagné

6.5.1 Consignes

— Télécharger les fichiers [Link] et [Link].


— Sassurer que le code fonctionne en lançant python3 [Link].
— À ce stade, vous devriez constater plusieurs problèmes :
— Au lieu davoir un mot au hasard, le mot à deviner est toujours accord.
— Au lieu dafficher un indice, le code affiche une liste de tentatives.
— Le jeu est impossible à gagner parce que la fonction a_gagné renvoie toujours False.
Le but de lexercice est de corriger ces 3 problèmes.

6.5. Exercice 37
Programmation en Python

38 Chapitre 6. Chapitre 6 - Listes


CHAPITRE 7

Chapitre 7 - None et pass

7.1 None

7.1.1 Définition

None est un mot-clé qui sert à représenter labsence.


Un peu comme True et False qui sont des mot-clés qui représentent des booléens.

7.1.2 Retourner None

En réalité, toutes les fonctions python retournent quelque chose, même quand elles ne contiennent pas le mot-clé
return.

def ne_renvoie_rien():
x = 2

resultat = ne_renvoie_rien()

print(resultat)
# affiche: None

39
Programmation en Python

7.1.3 Opérations avec None

La plupart des fonctions que nous avons vu échouent si on leur passe None en argument :

x = len(None)
# erreur: TypeError

x = None < 3
# erreur: TypeError

x = int(None)
# erreur: TypeError

Mais str() fonctionne :

x = str(None)
print(x)
# affiche: 'None'

On peut vérifier si une variable vaut None avec is None :

x = ne_renvoie_rien()
print(x is None)
# affiche: True

7.1.4 Example dutilisation

def trouve_dans_liste(valeur, liste):


for element in liste:
if element == valeur:
return element
return None

x = trouve_dans_liste(2, [1, 2, 3])


print(x)
# affiche: 2

x = trouve_dans_liste(1, [3, 4])


print(x)
# affiche: None

7.2 pass

À cause de lorganisation du flot de contrôle en blocs indentés, on ne peut pas vraiment avoir de blocs vides. Mais
parfois, on a besoin dun bloc qui ne fasse rien - cest là que le mot-clé pass rentre en jeu.
pass représente une instruction qui ne fait rien.
Un exemple :

40 Chapitre 7. Chapitre 7 - None et pass


Programmation en Python

une_condition = False
if une_condition:
pass
else:
print("une_condition n'est pas vraie")

On peut aussi - et cest lusage le plus courant - utiliser pass pour définir une fonction qui ne fait rien :

def ne_fait_rien():
pass

7.2. pass 41
Programmation en Python

42 Chapitre 7. Chapitre 7 - None et pass


CHAPITRE 8

Chapitre 8 - Dictionnaires

8.1 Principes fondamentaux

8.1.1 Définition

Un dictionnaire est une association entre des clés et des valeurs.


— les clés sont uniques ;
— les valeurs sont arbitraires.

8.1.2 Création de dictionnaires

Les dictionnaires sont créés avec des accolades : {, } :

dictionnaire_vide = {}

Ensuite, on utilise : pour séparer la clé et la valeur. Enfin, les paires de clé/valeur sont séparées par des virgules , :

une_clé_une_valeur = {"a": 42}

deux_clés_deux_valeurs = {"a": 42, "b": 53}

43
Programmation en Python

8.1.3 Accès aux valeurs

Avec [], comme pour les listes, mais avec une clé à la place dun index :

scores = {"john": 10, "bob": 42}

print(scores["john"])
# affiche: 10

print(scores["bob"])
# affiche: 42

print(scores["charlie"])
# erreur: KeyError

8.1.4 Modifier la valeur dune clé

Comme pour les listes, avec une assignation :

scores = {"john": 10, "bob": 42}


scores["john"] = 20
print(scores)
# affiche: {"john": 20, "bob": 42}

8.1.5 Créer une nouvelle clé

Même mécanisme que pour la modification des clés existantes :

scores = {"john": 10, "bob": 42}


scores["charlie"] = 30
print(scores)
# affiche: {"john": 20, "bob": 42, "charlie": 30}

rappel : Ceci ne fonctionne pas avec les listes. On ne peut pas ńăcréerăż de nouveaux éléments dans la liste juste avec
un index :

ma_liste = ["a", "b"]


ma_liste[1] = "c"
print(ma_liste)
# affiche: ["a", "c"]

ma_liste[3] = "d"
# erreur: IndexError

44 Chapitre 8. Chapitre 8 - Dictionnaires


Programmation en Python

8.1.6 del

Détruire une clé

Avec del - un nouveau mot-clé :

scores = {"john": 10, "bob": 42}


del scores["bob"]
print(scores)
# affiche: {"john": 10}

Détruire un élément dune liste

Aussi avec del :

fruits = ["pomme", "banane", "poire"]


del fruits[1]
print(fruits)
# affiche: ["pomme", "poire"]

Détruire une variable

Encore et toujours del :

mon_entier = 42
mon_entier += 3
print(mon_entier)
# affiche: 45

del mon_entier
mon_entier += 1
# erreur: NameError

8.2 Itération et dictionnaires

8.2.1 Itérer sur les clés

Avec for ... in ..., comme pour les listes :

scores = {"john": 10, "bob": 42}


for nom in scores:
# on assigne la valeur "john" à la variable `nom`, puis "bob"
score_associé_au_nom = scores[nom]
# on assigne la valeur 10 puis la valeur 42 à la variable
# score_associé_au_nom
print(nom, score_associé_au_nom)

john 10
bob 42

8.2. Itération et dictionnaires 45


Programmation en Python

8.3 Dictionnaires et booléens

8.3.1 Falsy et truthy

Les dictionnaires vides sont falsy, et tous les autres dictionnaires sont truthy :

mon_dico = {"a": 1, "b": 2}


if mon_dico:
print("mon_dico est truthy")
else:
print("mon_dico est falsy")
# affiche: mon_dico est truthy

mon_autre_dico = {}
if mon_autre_dico:
print("mon_autre_dico n'est pas vide")
else:
print("mon_autre_dico est vide")
# affiche: mon_autre_dico est vide

8.3.2 Test dappartenance

On peut vérifier si une clé est présente dans un dictionnaire avec le mot clé in, un peu comme pour les listes :

scores = {"john": 10, "bob": 42}


print("john" in scores)
# affiche: True

print("charlie" in scores)
# affiche: False

8.3.3 Comparaisons de dictionnaires

Deux dictionnaires sont considérés égaux sils ont les mêmes clés et les mêmes valeurs. Lordre na pas dimportance :

{"a":1, "b":2} == {"a":1, "b":2} # True


{"a":1, "b":2} == {"b":2, "a":1} # True
{"a":1, "b":2} == {"a":1, "b":3} # False

8.4 Exercice

8.4.1 Consignes

Le but de lexercice est dimplémenter un convertisseur dunités de distance.


Il faut être capable de convertir des kilomètres, des milles, des yards, etc.
Le programme doit sutiliser comme suit :

46 Chapitre 8. Chapitre 8 - Dictionnaires


Programmation en Python

python [Link] 1 km mi

Il y a trois ńămotsăż après le nom du fichier, séparés par des espaces. On appelle ces mots les ńăargumentsăż du
programme.
Ici, 1 est la valeur de départ, km labréviation de lunité de départ et mi labréviation de lunité darrivée.
Voici un tableau pour vous aider :

Nom Abréviation Valeur en mètres


mètre m 1
kilomètre km 1000
mille mi 1609.344
yard yd 0.9144

8.4.2 Squelette

Vous pouvez partir du code suivant :


import sys

def trouver_coefficient(unité):
return 1.0

def conversion_en_mètres(valeur, unité_de_départ):


coefficient = trouver_coefficient(unité_de_départ)
return valeur * coefficient

def conversion_depuis_mètres(valeur, unité_d_arrivée):


return 1.0

def convertir(valeur, unité_de_départ, unité_d_arrivée):


print("Conversion de", valeur, "en", unité_de_départ, "vers", unité_d_arrivée)
en_mètres = conversion_en_mètres(valeur, unité_de_départ)
résultat = conversion_depuis_mètres(en_mètres, unité_d_arrivée)
return résultat

def main():
nombre_arguments = len([Link]) - 1
if nombre_arguments != 3:
print("3 arguments attendus, mais", nombre_arguments, "reçu(s)")
return
valeur = float([Link][1])
unité_de_départ = [Link][2]
unité_d_arrivée = [Link][3]
valeur_de_sortie = convertir(valeur, unité_de_départ, unité_d_arrivée)
print("{:.6}".format(valeur_de_sortie))
(suite sur la page suivante)

8.4. Exercice 47
Programmation en Python

(suite de la page précédente)

main()

Vous noterez que le programme est capable de récupérer la valeur, lunité de départ et lunité darrivée correctement,
mais que le résultat est toujours égal à 1.0.
Votre objectif est de finir limplémentation pour réaliser effectivement la conversion.
À noter : vous navez pas besoin de changer limplémentation des fonctions main() et convertir(), et ne vous in-
quiétez pas si vous ne comprenez pas exactement ce que fait la fonction main(), on expliquera en détail comment
elle fonctionne dans un chapitre ultérieur. Pour terminer lexercice, vous navez besoin que de modifier les fonctions
trouver_coefficient(), conversion_en_mètres() et conversion_depuis_mètres().
À vous de jouer !

48 Chapitre 8. Chapitre 8 - Dictionnaires


CHAPITRE 9

Chapitre 9 - Tuples

9.1 Définition

Un tuple est un ensemble ordonné et immuable déléments (il est aussi appelé n-uplet dans la documentation Python).
Le nombre, lordre et la valeur des éléments sont fixes.

9.2 Création de tuples

Avec des parenthèses :

tuple_vide = ()
tuple_à_un_élement = (1,) # notez la virgule
tuple_à_deux_éléments = (1, 2) # on dit aussi: "couple"

Sauf pour le tuple vide, cest la virgule qui fait le tuple.


Note : tous les tuples sont truthy, sauf les tuples vides.

9.3 Tuples hétérogènes

Comme les listes, les tuples peuvent contenir des éléments de types différents :

# Un entier et une string


mon_tuple = (42, "bonjour")

# Un entier et un autre tuple


mon_tuple = (21, (True, "au revoir"))

49
Programmation en Python

9.4 Accès

Avec [] et lindex de lélément dans le tuple :

mon_tuple = (42, "bonjour")


print(mon_tuple[0])
# affiche: 42

print(mon_tuple[1])
# affiche: "bonjour"

9.5 Modification

Cest interdit :

mon_tuple = (42, "bonjour")


mon_tuple[0] = 44
# erreur: TypeError: 'tuple' object does not support item assignment

9.6 Test dappartenance

Avec in :

mon_tuple = (42, 14)


print(42 in mon_tuple)
# affiche: True

print(14 in mon_tuple)
# affiche: True

print(13 in mon_tuple)
# affiche: False

9.7 Dissociation

Créer plusieurs variables, à partir dun tuple, en une seule ligne :

couple = ("Batman", "Robin")


héros, side_kick = couple
print(héros)
# affiche: Batman

print(side_kick)
# affiche: Robin

50 Chapitre 9. Chapitre 9 - Tuples


Programmation en Python

9.8 Quelques erreurs classiques

héros, side_kick, ennemi = couple


# erreur: ValueError (3 != 2)

(héros,) = couple
# erreur: ValueError (1 != 2)

# Gare à la virgule:
héros, = couple
# erreur: ValueError (1 != 2)

9.9 Pièges

f(a, b, c) # appelle f() avec trois arguments

f((a, b, c)) # appelle f() avec un seul argument


# (qui est lui-même un tuple de 3 valeurs)

f(()) # appelle f() avec un tuple vide

(a) # juste la variable a entre parenthèses


(a,) # un tuple à un élément, qui vaut la valeur de a

On peut aussi déstructurer des listes :

fruits = ["pomme", "banane", "orange"]


premier, deuxième, troisième = fruits

print(premier)
# affiche: pomme

print(deuxième)
# affiche: banane

print(troisième)
# affiche: orange

On dit aussi dissociation ou unpacking.

9.8. Quelques erreurs classiques 51


Programmation en Python

9.10 Utilisations des tuples

Pour simplifier des conditions :

# Avant:
if (
ma_valeur == "nord" or
ma_valeur == "sud" or
ma_valeur == "ouest" or
ma_valeur == "est"):
print("direction", ma_valeur)

# Après:
if ma_valeur in ("nord", "sud", "est", "ouest"):
print("direction", ma_valeur)

Pour retourner plusieurs valeurs :

def tire_carte():
valeur = "10"
couleur = "trèfle"
return (valeur, couleur)

v, c = tire_carte()
print(v, "de", c)
# affiche: 10 de trèfle

Ce nest pas une nouvelle syntaxe, juste de la manipulation de tuples !

52 Chapitre 9. Chapitre 9 - Tuples


CHAPITRE 10

Chapitre 10 - Introduction aux classes

Ce quon a vu jusquici :
— des types simples (entiers, booléens, ) ;
— des structures de données (listes, dictionnaires, ) ;
— des fonctions qui manipulent ces types ou ces structures de données ;
— ds fonctions qui sappellent les unes les autres.
On appelle cet ensemble de concepts, cette façon décrire du code, un paradigme, et cest un paradigme procédural.
On va passer à un autre paradigme : lorienté objet.

10.1 Orienté objet - une première définition

Un ńăobjetăż informatique représente un véritable ńăobjetăż physique dans le vrai monde.


Ce nest pas une très bonne définition :
1. Ce nest pas nécessaire ;
2. Ce nest même pas forcément souhaitable !
Je le mentionne juste parce que cest une idée reçue très répandue.

10.2 Orienté objet - 2ème définition

Une meilleure définition, cest de dire que la programmation orientée objet permet de mettre au même endroit :
— des données ;
— des fonctions qui opèrent sur ces données.
Limportant cest que les deux aillent ensemble !
Note : ce nest pas la meilleure définition de lorienté objet, mais on sen contentera pour le moment

53
Programmation en Python

10.3 Les classes

On va parler dune façon de faire de lorienté objet : avec des classes.


Mais notez bien quon peut faire de lorienté objet sans classes !

10.4 Le plan de construction

On dit souvent quen Python, ńătout est objetăż.


Pour bien comprendre cela, il faut dabord parler des classes et des instances de classes.
Une classe est un plan de construction, et est définie avec le mot-clé class, suivi du nom de la classe :

class MaClasse:
# du code ici

Notez quon nutilise pas le snake case pour les noms de classes, mais le Pascal Case (ou Camel Case) : Le nom
commence par une majuscule, et on alterne minuscules et majuscules pour séparer les mots.
Comme les fonctions, les classes contiennent un corps, qui est le bloc indenté en dessous du mot-clé class, de nom
de la classe et du : en fin de ligne.
Les classes sont utilisées pour construire des instances.

10.5 Créons des instances

On peut faire un plan de construction vide avec le mot-clé pass :

class MaClasse:
pass

Dans ce cas, on crée une instance en mettant le nom de la classe suivi dune paire de parenthèses, un peu comme pour
appeler une fonction :

mon_instance = MaClasse()

Ici, mon_instance est une instance de la classe MaClasse. Notez que mon_instance utilise snake case, comme
toutes les variables quon a vues jusquici.

10.6 Attributs

Les attributs sont des éléments nommés à lintérieur dune instance.


On peut y accéder avec la syntaxe <instance>.<attribut> :

y = a.x

Ici, y est lattribut x de linstance a.


Les attributs peuvent être des fonctions :

54 Chapitre 10. Chapitre 10 - Introduction aux classes


Programmation en Python

func = a.x
func(10)

Ici, on crée une variable func qui prend la valeur de lattribut x dans linstance a, puis on lappelle avec largument 10 à
la ligne suivante.
Le code suivant fait exactement la même chose, mais avec une ligne de moins :

a.x(10)

On peut créer des attributs dans nimporte quel instance, en utilisant lassignation :

mon_instance = MaClasse()

# Création de l'attribut `x` dans `mon_instance`


mon_instance.x = 42

# Accés à l'attribut `x` dans `mon_instance`


print(mon_instance.x)
# affiche: 42

Ici, on assigne la valeur 42 à lattribut x de linstance mon_instance.

10.7 Méthodes - définition

On peut aussi mettre des méthodes dans des classes.


On utilise le mot-clé def, comme pour les fonctions, mais les méthodes doivent avoir au moins un argument appelé
self, et être à lintérieur du bloc de la classe :

class MaClasse:
def ma_méthode(self):
return 42

Notez que les méthodes sont aussi des attributs. Leur valeur est une fonction qui se comporte légèrement différemment
des fonctions quon a vu jusquici.

10.8 Méthodes - appel

Une méthode ne peut être appelée que depuis une instance de la classe :

class MaClasse:
def ma_méthode(self):
return 42

ma_méthode()
# erreur: NameError

mon_instance = MaClasse()
résultat = mon_instance.ma_méthode()
print(résultat)
# affiche: 42

10.7. Méthodes - définition 55


Programmation en Python

Notez quon ne passe pas dargument quand on appelle ma_méthode depuis linstance.

10.9 Méthodes et attributs

self prend la valeur de linstance courante quand la méthode est appelée.


On peut le voir en utilisant des attributs :

class MaClasse:
def affiche_attribut_x(self):
# Accès à l'attribut `x` dans `self`
print(self.x)

mon_instance = MaClasse()
mon_instance.x = 42
mon_instance.affiche_attribut_x()
# affiche: 42

On peut aussi créer des attributs dans une méthode :

class MaClasse:
def crée_attribut_x(self):
self.x = 42
def affiche_attribut_x(self):
print(self.x)

mon_instance = MaClasse()
mon_instance.affiche_attribut_x()
# erreur: `mon_instance` n'a pas d'attribut `x`

mon_instance.crée_attribut_x()
mon_instance.affiche_attribut_x()
# affiche: 42

Les méthodes peuvent aussi prendre plusieurs arguments, en plus de self, mais self doit toujours être le premier
argument.
Par example, pour créer un attribut avec une certaine valeur :

class MaClasse
def crée_attribut_x(self, valeur_de_x):
self.x = valeur_de_x

def affiche_attribut_x(self);
print(self.x)

mon_instance = MaClasse()
mon_instance.crée_attribut_x(42)
mon_instance.affiche_attribut_x()
# affiche: 42

56 Chapitre 10. Chapitre 10 - Introduction aux classes


Programmation en Python

10.10 Méthodes appelant dautres méthodes

Comme les méthodes sont aussi des attributs, les méthodes dune instance peuvent sappeler les unes les autres :

class MaClasse:
def méthode_1(self):
print("démarrage de la méthode 1")
print("la méthode 1 affiche bonjour")
print("bonjour")
print("fin de la méthode 1")

def méthode_2(self):
print("la méthode 2 appelle la méthode 1")
self.méthode_1()
print("fin de la méthode 2")

mon_instance = MaClasse()
mon_instance.méthode_2()

la méthode 2 appelle la méthode 1


démarrage de la méthode 1
la méthode 1 affiche bonjour
bonjour
fin de la méthode 1
fin de la méthode 2

10.11 Une méthode spéciale

Si vous définissez une méthode nommée __init__, celle-ci est appelée automatiquement quand linstance est
construite.
On dit que cest une méthode ńămagiqueăż parce quelle fait quelque chose sans quon lappelle explicitement.
On utilise souvent __init__ pour créer des attributs :

class MaClasse:
def __init__(self):
self.x = 1
self.y = 2

mon_instance = MaClasse()

# __init__ est appelée automatiquement!


print(mon_instance.x)
# affiche: 1
print(mon_instance.y)
# affiche: 2

On prend souvent les valeurs des attributs à créer en arguments de la méthode __init__ :

10.10. Méthodes appelant dautres méthodes 57


Programmation en Python

class MaClasse:
def __init__(self, x, y):
self.x = x
self.y = y

Dans ce cas, les arguments de la méthode __init__ apparaissent à lintérieur des parenthèses après le nom de la classe :

mon_instance = MaClasse(3, 4)
print(mon_instance.x)
# affiche: 3
print(mon_instance.y)
# affiche: 4

Note : Pour cette raison, __init__ est souvent appelé le constructeur de la classe.

10.12 Les constructeurs en pratique

Une bonne pratique consiste à créer tous les attributs nécessaires dans le constructeur.
Si les atttributs ont une valeur par défaut, ou une valeur initiale, on peut les créer dans le constructeur directement.
Sinon, on créera lattribut avec une valeur qui viendra dun paramètre du constructeur (souvent avec le même nom)
Premier example :

class Point2D:
# x et y n'ont pas de bonne valeur par défault,
# donc on utilise un constructeur qui prend
# x et y en paramètre
def __init__(self, x, y):
self.x = x
self.y = y

origine = Point2D(0, 0)

Deuxième example :

class Joueur:
# Quand on crée un joueur, il a un score à 0
def __init__(self, nom):
[Link] = nom
[Link] = 0

alice = Joueur("alice")

58 Chapitre 10. Chapitre 10 - Introduction aux classes


Programmation en Python

10.13 Récapitulatif

— Classe : plan de construction.


— Instance : valeur issue dune classe.
— Attribut : variable dans une instance.
— Méthode : fonction dans une instance (qui prend self en premier argument).
— __init__ : méthode magique appelée automatiquement pendant linstanciation.

10.14 Classes et programmation orienté objet

Ainsi, on peut ranger au même endroit des données et des fonctions opérant sur ces données.
Les données sont les attributs, et les fonctions opérant sur ces attributs sont les méthodes.
On peut ainsi séparer les responsabilités à lintérieur dun code en les répartissant entre plusieurs classes.

10.13. Récapitulatif 59
Programmation en Python

60 Chapitre 10. Chapitre 10 - Introduction aux classes


CHAPITRE 11

Chapitre 11 - Introduction aux modules

11.1 Un fichier = un module

Et oui, vous faites des modules sans le savoir depuis le début :)


Un fichier [Link] correspond toujours module foo
Attention : Ce nest pas tout à fait réciproque. Le module foo peut venir dautre chose quun fichier [Link].

11.2 Importer un module

Ou : accéder à du code provenant dun autre fichier source.


Créons un fichier [Link] contenant seulement une assignation de lentier 42 à la variable a :

# Dans [Link]
a = 42

Comme un fichier = un module, on vient de créé un module bonjour contenant une variable a.
Si maintenant on crée un fichier [Link] dans le même répertoire, on peut accéder à cette variable en impor-
tant le module avec le mot-clé import :

# Dans [Link]
import bonjour
print(bonjour.a)
# affiche: 42

Note : Le nom du module est écrit directement, ce nest pas une chaîne de caractères.

On voit que la variable a dans [Link] est devenue un attribut du module bonjour lorsquil a été importé.

61
Programmation en Python

Si maintenant on rajoute une fonction dire_bonjour dans [Link] :

# Dans [Link]
a = 42
def dire_bonjour():
print("Bonjour!")

On peut appeler la fonction dire_bonjour() depuis [Link] en utilisant la méthode dire_bonjour() du


module bonjour :

# Dans [Link]
import bonjour
bonjour.dire_bonjour()
# affiche: Bonjour!

11.3 Les imports ne sont faits quune seule fois

Il est important de noter que :


— tout le code à lintérieur dun module est exécuté lors du premier import ;
— mais il nest pas ré-exécuté si le module a déjà été importé auparavant.
On peut le voir en mettant du code dans [Link], en plus des simples définitions de fonctions et de créations de
variables :

# Dans [Link]
print("Je suis le module bonjour et tu viens de mimporter")
def dire_bonjour():
....

# Dans [Link]
import bonjour
# affiche: Je suis le module bonjour et tu viens de mimporter

import bonjour
# affiche: rien

11.4 La bibliothèque standard

La bibliothèque standard est une collection de modules directement utilisables fournis à linstallation de Python.
Exemple : sys, random,
Toute la bibliothèque standard est documentée, et la traduction en Français est en cours :
[Link]
Mettez ce lien dans vos favoris, il vous sera très utile.

62 Chapitre 11. Chapitre 11 - Introduction aux modules


Programmation en Python

11.5 Quelques exemples de modules de la bibliothèque standard

11.5.1 Easter eggs

(Ou fonctionnalités cachées)


— import antigravity
— import this
Je vous laisse découvrir ce que fait le premier. Quant au deuxième, il contient une liste de préceptes que la plupart des
développeurs Python sefforcent de respecter. On en reparlera

11.5. Quelques exemples de modules de la bibliothèque standard 63


Programmation en Python

64 Chapitre 11. Chapitre 11 - Introduction aux modules


CHAPITRE 12

Chapitre 12 - Couplage et composition

12.1 Couplage

12.1.1 Définition

Un couplage décrit une relation entre deux classes.

12.1.2 Exemple

Ici on veut représenter des chats et des humains qui adoptent (ou non) des chats. Tous les chats ont un nom, et tous les
humains ont un prénom.
On peut utiliser pour cela deux classes : Chat et Humain.

class Chat:
def __init__(self, nom):
[Link] = nom

chat = Chat("Monsieur Moustaches")


prin([Link])
# affiche: Monsieur Moustaches

class Humain:
def __init__(self, prénom):
[Link]énom = prénom

alice = Humain(prénom="Alice")
print([Link]énom)
# affiche: Alice

Maintenant on veut que les humains puissent adopter des chats. Pour cela, on peut ajouter la méthode adopte() dans
la classe Humain.

65
Programmation en Python

Cette méthode va prendre un argument, une instance de la classe Chat :

class Humain:
def __init__(self, prénom):
[Link]énom = prénom

def adopte(self, chat):


print([Link]énom, "adopte un chat")

boule_de_poils = Chat("Boule de Poils")


alice = Humain("Alice")
[Link](boule_de_poils)
# affiche: "Alice adopte un chat"

On peut accéder au nom du chat depuis la méthode adopte(), en utilisant la syntaxe [Link] vue précédem-
ment :

class Humain:
def __init__(self, prénom):
[Link]énom = prénom

def adopte(self, chat):


print([Link]énom, "adopte", [Link])

boule_de_poils = Chat("Boule de Poils")


alice = Humain("Alice")
[Link](boule_de_poils)
# affiche: Alice adopte Boule de Poils

12.1.3 Couplage

class Humain:
...
def adopte(self, chat):
print([Link]énom, "adopte", [Link])

Notez également que nous avons écrit [Link]. ainsi, la méthode adopte() ne peut être appelée que par une instance
qui a un attribut nom, sinon on aura une erreur.
Donc si on modifie la classe Chat et quon renomme lattribut nom en surnom par exemple, la méthode adopte() de
la classe Humain cessera de fonctionner : on dit quon a un couplage entre les classes Chat et Humain.

12.2 Composition

12.2.1 Définition

Une classe à lintérieur dune autre classe.

66 Chapitre 12. Chapitre 12 - Couplage et composition


Programmation en Python

12.2.2 Dépendances entre fonctions

Exemple :

def calcule_x():
...
# du code ici

def fait_un_truc_avec_x(x):
...
# du code ici

x = calcule_x()
fait_un_truc_avec_x(x)

On voit que la fonction fait_un_truc_avec_x() prend un argument x, qui est retourné par la fonction calcule_x().
fait_un_truc_avec_x() doit donc être appelée après calcule_x(). On dit que fait_un_truc_avec_x() dépend
de calcule_x().

12.2.3 Dépendances entre classes

Un bon moyen dintroduire une dépendance entre deux classes est dutiliser les constructeurs.
Revoyons la classe Chat :

class Chat:
def __init__(self, nom):
[Link] = nom

Comme le constructeur de la classe Chat prend un nom en argument, il est impossible de construire des chats sans
nom :

chat = Chat()
# erreur: TypeError: __init__() missing 1 required positional argument: 'nom'

De la même façon, si on veut que tous les enfants aient un chat (pourquoi pas, après tout), on peut avoir une classe
Enfant, dont le constructeur prend une instance de chat en plus du prénom :

class Enfant:
def __init__(self, prénom, chat):
[Link]énom = prénom
[Link] = chat

alice = Enfant("Alice")
# erreur: TypeError: __init__() missing 1 required positional argument: 'chat'

boule_de_poils = Chat("Boule de Poils")


alice = Enfant("Alice", boule_de_poils)
# OK!

12.2. Composition 67
Programmation en Python

12.2.4 Utilisation de la composition

Maintenant quon vit dans un monde où tous les enfants ont chacun un chat, on peut par exemple consoler tous les
enfants en leur demandant de caresser leur chat, chat qui va ronronner et faire plaisir à son propriétaire.
voici comment on peut coder cela : dabord, on rajoute les méthodes caresse() et ronronne() dans la classe chat :

class Chat:
def __init__(self, nom):
[Link] = nom

def ronronne(self):
print([Link], 'fait: "prrrrr"')

def caresse(self):
[Link]()

boule_de_poils = Chat("Boule de Poils")


boule_de_poils.caresse()
# affiche: Boule de Poils fait "prrrrr"

Ensuite, on peut rajouter la méthode console() dans la classe Enfant, qui va :


— récupérer linstance de la classe Chat dans self, comme nimporte quel attribut ;
— puis appeler la méthode caresse() de cette instance :

class Enfant:
def __init__(self, prénom, chat):
[Link]énom = prénom
[Link] = chat

def console(self):
[Link]()
Si on combine ces deux classes dans le même morceau de code et quon exécute les instructions suivantes :

boule_de_poils = Chat("Boule de Poils")


alice = Enfant("Alice", boule_de_poils)
[Link]()

On affichera `Boule de Poils fait "prrr" et Alice sera consolée.


On dit parfois quon a délégué limplémentation de la méthode console() de la classe Enfant à la méthode caresse()
de la classe Chat.

68 Chapitre 12. Chapitre 12 - Couplage et composition


CHAPITRE 13

Chapitre 13 - Bibliothèques

13.1 Introduction

13.1.1 Importer un module

Souvenez-vous, dans le chapitre 12, nous avons vu que le code suivant fonctionne sil y a un ficher [Link] quelque part
qui contient la fonction bar :

import foo
[Link]()

Ce fichier peut être présent soit dans le répertoire courant, soit dans la bibliothèque standard Python.

13.1.2 La variable PATH

Vous connaissez peut-être le rôle de la variable denvironnement PATH. Celle-ci contient une liste de chemins, séparés
par le caractère : et est utilisée par votre shell pour trouver le chemin complet des commandes que vous lancez.
Par exemple :

PATH="/bin:/usr/bin:/usr/sbin"
$ ifconfig
# lance le binaire /usr/sbin/ifconfig
$ ls
# lance le binaire /bin/ls

Le chemin est ńărésoluăż par le shell en parcourant la liste de tout les chemins de la variable PATH, et en regardant si
le chemin complet existe. La résolution sarrête dès le premier chemin trouvé.
Par exemple, si vous avez PATH="/home/user/bin:/usr/bin" et un fichier ls dans /home/user/bin/ls, cest
cette commande-là (et non /bin/ls) qui sera utilisé quand vous taperez ls.

69
Programmation en Python

13.2 [Link]

En Python, il existe une variable path prédéfinie dans le module sys qui fonctionne de manière similaire à la variable
denvironnement PATH.
Si jessaye de lafficher sur ma machine, voici ce que jobtiens :

import sys
print([Link])

[
"",
"/usr/lib/python3.8",
"/usr/lib/python3.8/lib-dynload",
"/home/dmerej/.local/lib/python3.8/",
"/usr/lib/python3.8/site-packages",
]

Le résultat dépend :
— du système dexploitation ;
— de la façon dont Python a été installé ;
— et de la présence ou non de certains répertoires.

En fait, [Link] est construit dynamiquement par linterpréteur Python lors de son démarrage.
Notez également que [Link] commence par une chaîne vide. En pratique, cela signifie que le répertoire courant à
la priorité sur tout le reste.

13.2.1 Priorité du répertoire courant

Prenons un exemple. Si vous ouvrez un explorateur de fichiers dans le deuxième élément de la liste de [Link]
(/usr/lib/python3.8/ sur ma machine), vous trouverez un grand nombre de fichiers Python.
Notamment, vous devriez trouver un fichier [Link] dans ce répertoire.
En fait, vous trouverez la plupart des modules de la bibliothèque standard dans ce répertoire.
Maintenant, imaginons que vous avez un deuxième fichier [Link] dans votre répertoire courant. Finalement, ima-
ginez que vous lancez un fichier [Link] contentant import random dans ce même répertoire.
Et bien, cest le fichier [Link] de votre répertoire qui sera utilisé, et non celui de la bibliothèque standard !

13.2.2 Permissions des répertoires de [Link]

Un autre aspect notable de [Link] est quil ne contient que deux répertoires dans lesquels lutilisateur courant peut
potentiellement écrire : le chemin courant et le chemin dans ~/.local/lib. Tous les autres (/usr/lib/python3.8/,
etc.) sont des chemins ńăsystèmeăż et ne peuvent être modifiés que par un compte administrateur (avec root ou sudo,
donc).
La situation est semblable sur macOS et Windows.

70 Chapitre 13. Chapitre 13 - Bibliothèques


Programmation en Python

13.3 Bibliothèques tierces

Prenons un exemple :

# dans [Link]
import tabulate

scores = [
["John", 345],
["Mary-Jane", 2],
["Bob", 543],
]
table = [Link](scores)
print(table)

$ python3 [Link]
--------- ---
John 345
Mary-Jane 2
Bob 543
--------- ---

Ici, le module tabulate nest ni dans la bibliothèque standard, ni écrit par lauteur du script [Link]. On dit que cest
une bibliothèque tierce.
On peut trouver le code source de tabulate facilement. La question qui se pose alors est : Comment faire en sorte que
[Link] contienne le module tabulate ?
Eh bien, plusieurs solutions soffrent à vous.

13.3.1 Le gestionnaire de paquets

Si vous utilisez une distribution Linux, peut-être pourrez-vous utiliser votre gestionnaire de paquets :

$ sudo apt install python3-tabulate

Comme vous lancez votre gestionnaire de paquets avec sudo, celui-ci sera capable décrire dans les chemins système
de [Link].

13.3.2 À la main

Une autre méthode consiste à partir des sources : Par exemple, si le paquet de votre distribution nest pas assez récent,
ou si vous avez besoin de modifier le code de la bibliothèque en question.
Voici une marche à suivre possible :
1. Récupérer les sources de la version qui vous intéresse dans la section téléchargement de bitbucket ;
2. Extraire larchive, par exemple dans src/tabulate ;
3. Se rendre dans src/tabulate et lancer python3 [Link] install --user.

13.3. Bibliothèques tierces 71


Programmation en Python

13.3.3 Anatomie du fichier [Link]

La plupart des bibliothèques Python contiennent un [Link] à la racine de leurs sources. Il sert à plein de choses, la
commande install nétant quune parmi dautres.
Le fichier [Link] contient en général simplement un import de setuptools, et un appel à la fonction setup(),
avec de nombreux arguments :

# tabulate/[Link]
from setuptools import setup

setup(
name='tabulate',
version='0.8.1',
description='Pretty-print tabular data',
py_modules=["tabulate"],
scripts=["bin/tabulate"],
...
)

13.3.4 Résultat de linvocation de [Link]

Par défaut, [Link] essaiera décrire dans un des chemins système de [Link], doù lutilisation de loption --user.
Voici à quoi ressemble la sortie de la commande :

$ cd src/tabulate
$ python3 [Link] install --user
running install
...
Copying [Link] to /home/dmerej/.local/lib/python3.7/site-packages
...
Installing tabulate script to /home/dmerej/.local/bin

Notez que le module a été copié dans ~/.local/lib/python3.7/site-packages/ et le script dans ~/.local/bin.
Cela signifie que tous les scripts Python lancés par lutilisateur courant auront accès au module tabulate.
Notez également quun script a été installé dans ~/.local/bin. Une bibliothèque Python peut contenir aussi bien des
modules que des scripts.
Un point important est que vous navez en général pas besoin de lancer le script directement. Vous pouvez utiliser
python3 -m tabulate. Procéder de cette façon est intéressant puisque vous navez pas à vous soucier de rajouter le
chemin dinstallation des scripts dans la variable denvironnement PATH.

13.4 Dépendances

Prenons une autre bibliothèque : cli-ui.


Elle permet dafficher du texte en couleur dans un terminal :

import cli_ui

cli_ui.info("Ceci est en", cli_ui.red, "rouge")

72 Chapitre 13. Chapitre 13 - Bibliothèques


Programmation en Python

Elle permet également dafficher des tableaux en couleur :

headers=["name", "score"]
data = [
[(bold, "John"), (green, 10.0)],
[(bold, "Jane"), (green, 5.0)],
]
cli_ui.info_table(data, headers=headers)

Pour ce faire, elle repose sur la bibliothèque tabulate vue précédemment. On dit que cli-ui dépend de tabulate.

13.4.1 Déclaration des dépendances

La déclaration de la dépendance de cli-ui vers tabulate seffectue également dans le fichier [Link] :

setup(
name="cli-ui",
version="0.9.1",
install_requires=[
"tabulate",
...
],
...
)

13.4.2 [Link]

On comprend dès lors quil doit nécessairement exister un annuaire permettant de relier les noms de dépendances à leur
code source.
Cet annuaire, cest le site [Link]. Vous y trouverez les pages correspondant à tabulate et cli-ui.

13.4.3 pip

pip est un outil qui est fréquemment installé en même temps que linterpréteur Python. Vous pouvez également linstaller
séparément grâce au script [Link], en lançant python3 [Link] --user.
Il est conseillé de toujours lancer pip avec python3 -m pip. De cette façon, vous êtes certains dutiliser le module
pip correspondant à votre binaire python3, et vous ne dépendez pas de ce quil y a dans votre PATH.
pip est capable dinterroger le site [Link] pour retrouver les dépendances, et également de lancer les différents
scripts [Link].
Comme de nombreux outils, il sutilise à laide de commandes. Voici comment installer cli-ui à laide de la commande
install de pip :

$ python3 -m pip install cli-ui --user


Collecting cli-ui
...
Requirement already satisfied: unidecode in /usr/lib/python3.7/site-packages (from cli-
,→ui) (1.0.23)

Requirement already satisfied: colorama in /usr/lib/python3.7/site-packages (from cli-


,→ui) (0.4.1)

(suite sur la page suivante)

13.4. Dépendances 73
Programmation en Python

(suite de la page précédente)


Requirement already satisfied: tabulate in /mnt/data/dmerej/src/python-tabulate (from␣
,→cli-ui) (0.8.4)

Installing collected packages: cli-ui


Successfully installed cli-ui-0.9.1

On constate ici quelques limitations de pip :


— Il faut penser à utiliser --user (de la même façon que lorsquon lance [Link] à la main).
— Si le paquet est déjà installé dans le système, pip ne saura pas le mettre à jour, il faudra passer par le gestionnaire
de paquet de la distribution.
En revanche, pip contient de nombreuses fonctionnalités intéressantes :
— Il est capable de désinstaller des bibliothèques (à condition toutefois quelles ne soient pas dans un répertoire
système).
— Il est aussi capable dafficher la liste complète des bibliothèques Python accessibles par lutilisateur courant avec
freeze.
Voici un extrait de la commande python3 -m pip freeze au moment de la rédaction de cet article sur ma machine :

$ python3 -m pip freeze


apipkg==1.5
cli-ui==0.9.1
gaupol==1.5
tabulate==0.8.4

On y retrouve les bibliothèques cli-ui et tabulate, bien sûr, mais aussi la bibliothèque gaupol, qui correspond au
programme dédition de sous-titres que jai installé à laide du gestionnaire de paquets de ma distribution. Précisons que
les modules de la bibliothèque standard et ceux utilisés directement par pip sont omis de la liste.
On constate également que chaque bibliothèque possède un numéro de version.

13.4.4 Numéros de version

Les numéros de version remplissent plusieurs rôles, mais lun des principaux est de spécifier des changements incom-
patibles.
Par exemple, pour cli-ui, la façon dappeler la fonction ask_choice a changé entre les versions 0.7 et 0.8, comme le
montre cet extrait du changelog :
The list of choices used by ask_choice is now a named keyword argument :

# Old (<= 0.7)


ask_choice("select a fruit", ["apple", "banana"])
# New (>= 0.8)
ask_choice("select a fruit", choices=["apple", "banana"])

Ceci sappelle un changement dAPI.

74 Chapitre 13. Chapitre 13 - Bibliothèques


Programmation en Python

13.4.5 Réagir aux changements dAPI

Plusieurs possibilités :
— On peut bien sûr adapter le code pour utiliser la nouvelle API, mais cela nest pas toujours possible ni souhaitable.
— Une autre solution est de spécifier des contraintes sur le numéro de version dans la déclaration des dépendances.
Par exemple :

setup(
install_requires=[
"cli-ui < 0.8",
...
]
)

13.4.6 Aparté : pourquoi éviter sudo pip

Souvenez-vous que les fichiers systèmes sont contrôlés par votre gestionnaire de paquets.
Les mainteneurs de votre distribution font en sorte quils fonctionnent bien les uns avec les autres. Par exemple, le paquet
python3-cli-ui ne sera mis à jour que lorsque tous les paquets qui en dépendent seront prêts à utiliser la nouvelle
API.
En revanche, si vous lancez sudo pip (où pip avec un compte root), vous allez écrire dans ces mêmes répertoire et
vous risquez de ńăcasserăż certains programmes de votre système.
Mais il y a un autre problème encore pire

13.4.7 Conflit de dépendances

Supposons deux projets A et B dans votre répertoire personnel. Ils dépendent tous les deux de cli-ui, mais lun des
deux utilise cli-ui 0.7 et lautre cli-ui 0.9. Que faire ?

13.5 Environnements virtuels

La solution est dutiliser un environnement virtuel (virtualenv en abrégé). Cest un répertoire isolé du reste du système.

13.5.1 Aparté : python3 -m venv sur Debian

La commande python3 -m venv fonctionne en général partout, dès linstallation de Python3 (out of the box, en Anglais),
sauf sur Debian et ses dérivées.
Si vous utilisez Debian, la commande pourrait ne pas fonctionner. En fonction des messages derreur que vous obtenez,
il est possible de résoudre le problème en :
— installant le paquet python3-venv ;
— ou en utilisant dabord pip pour installer virtualenv, avec python3 -m pip install virtualenv
--user puis en lançant python3 -m virtualenv foo-venv.

13.5. Environnements virtuels 75


Programmation en Python

13.5.2 Comportement de python dans le virtualenv

Ce répertoire contient de nombreux fichiers et dossiers, et notamment un binaire dans foo-venv/bin/python3.


Voyons comment il se comporte en le comparant au binaire /usr/bin/python3 habituel :

$ /usr/bin/python3 -c 'import sys; print([Link])'


['',
...
'/usr/lib/python3.7',
'/usr/lib/[Link]',
'/usr/lib/python3.7/lib-dynload',
'/home/dmerej/.local/lib/python3.7/site-packages',
'/usr/lib/python3.7/site-packages'
]

$ /home/dmerej/foo-venv/bin/python -c 'import sys; print([Link])'


['',
'/usr/lib/python3.7',
'/usr/lib/[Link]',
'/usr/lib/python3.7/lib-dynload',
'/home/dmerej/foo-venv/lib/python3.7/site-packages,
]

À noter :
— Le répertoire ńăglobalăż dans ~/.local/lib a disparu.
— Seuls quelques répertoires systèmes sont présents (ils correspondent plus ou moins à lemplacement des modules
de la bibliothèque standard).
— Un répertoire au sein du virtualenv a été ajouté.
Ainsi, lisolation du virtualenv est reflété dans la différence de la valeur de [Link].
Il faut aussi préciser que le virtualenv nest pas complètement isolé du reste du système. En particulier, il dépend encore
du binaire Python utilisé pour le créer.
Par exemple, si vous utilisez /usr/local/bin/python3.7 -m venv foo-37, le virtualenv dans foo-37 utilisera
Python 3.7 et fonctionnera tant que le binaire /usr/local/bin/python3.7 existe.
Cela signifie également quil est possible quen mettant à jour le paquet python3 sur votre distribution, vous rendiez
inutilisables les virtualenvs créés avec lancienne version du paquet.

13.5.3 Comportement de pip dans le virtualenv

Daprès ce qui précède, le virtualenv ne devrait contenir aucun module en dehors de la bibliothèque standard et de pip
lui-même.
On peut sen assurer en lançant python3 -m pip freeze depuis le virtualenv et en vérifiant que rien ne saffiche :

$ python3 -m pip freeze


# de nombreuses bibliothèques en dehors du virtualenv
apipkg==1.5
cli-ui==0.9.1
gaupol==1.5
tabulate==0.8.4

76 Chapitre 13. Chapitre 13 - Bibliothèques


Programmation en Python

$ /home/dmerej/foo-venv/bin/python3 -m pip freeze


# rien :)

On peut alors utiliser le module pip du virtualenv pour installer des bibliothèques dans celui-ci :

$ /home/dmerej/foo-venv/bin/python3 -m pip install cli-ui


Collecting cli-ui
Using cached [Link]
Collecting colorama (from cli-ui)
Using cached [Link]
Collecting unidecode (from cli-ui)
Using cached [Link]
Collecting tabulate (from cli-ui)
Installing collected packages: colorama, unidecode, tabulate, cli-ui
Successfully installed cli-ui-0.9.1 colorama-0.4.1 tabulate-0.8.3
unidecode-1.0.23

Cette fois, aucune bibliothèque nest marquée comme déjà installée, et on récupère donc cli-ui et toutes ses dépen-
dances.
On a enfin notre solution pour résoudre notre conflit de dépendances : On peut simplement créer un virtualenv par
projet. Ceci nous permettra davoir effectivement deux versions différentes de cli-ui, isolées les unes des autres.

13.5.4 Activer un virtualenv

Devoir préciser le chemin du virtualenv en entier pour chaque commande peut devenir fastidieux ; heureusement, il est
possible dactiver un virtualenv, en lançant une des commandes suivantes :
— source foo-venv/bin/activate, si vous utilisez un shell POSIX ;
— source foo-venv/bin/[Link], si vous utilisez Fish ;
— foo-venv\bin\[Link], sous Windows.
Une fois le virtualenv activé, taper python, python3 ou pip utilisera les binaires correspondants dans le virtualenv
automatiquement, et ce, tant que la session du shell sera ouverte.
Le script dactivation ne fait en réalité pas grand-chose à part modifier la variable PATH et rajouter le nom du virtualenv
au début de linvite de commandes :

# Avant
user@host:~/src $ source foo-env/bin/activate
# Après
(foo-env) user@host:~/src $

Pour sortir du virtualenv, entrez la commande deactivate.

13.5.5 Les environnements virtuels en pratique

Le système de gestions des dépendances de Python peut paraître compliqué et bizarre, surtout venant dautres langages.
Mon conseil est de toujours suivre ces deux règles :
— un virtualenv par projet ;
— toujours utiliser pip depuis un virtualenv.
Certes, cela peut paraître fastidieux, mais cest une méthode qui vous évitera probablement de vous arracher les cheveux
(croyez-en mon expérience).
Voici un exemple darborescence qui montre deux projets, projet-1 et projet-2, chacun avec son virtualenv dédié :

13.5. Environnements virtuels 77


Programmation en Python

projets
projet-1
projet_1.py
.venv
bin
include
lib
...
projet-2
projet_2.py
.venv
bin
include
lib
...

Notez bien que les sources de chaque projet projet_1.py et projet_2.py sont au même niveau que le répertoire
.venv et non à lintérieur de celui-ci.
Vous pouvez aussi retenir la règle suivante : étant donné un répertoire ńăXăż contenant les sources dun projet, les
commandes à lancer pour créer le virtualenv seront :

$ cd X/
$ python3 -m venv .venv

13.5.6 Pour conclure

Pour installer pandas dans le projet foo, trois étapes


1. Créer un virtualenv dans foo/.venv
2. Activer le virtualenv
3. Installer pandas en lançant pip install pandas depuis le virtualenv
Notez quil est possible de faire cela en passant par lIDE (VS Code ou PyCharm)

78 Chapitre 13. Chapitre 13 - Bibliothèques


CHAPITRE 14

Chapitre 14 - Données binaires et fichiers

On vous a peut-être déjà dit que linformatique consiste à manipuler des suites de 0 et et de 1, mais quen est-il exacte-
ment ?
De manière surprenante, la réponse à cette question va nous emmener sur un chemin qui va parler de maths, puis de
comment le langage Python peut interagir avec ńălextérieurăż.

14.1 Données binaires

14.1.1 Introduction : chiffres et nombres

Si je vous parle de ce que représente le texte 342 vous pouvez le voir de deux façons :
1. Cest une suite de chiffres : 3, puis 4, puis 2 ;
2. Cest un nombre (quelque part entre 300 et 350).
On se sert des chiffres de 0 à 9 pour représenter des nombres.

14.1.2 La base 10

Plus exactement, pour passer de la suite de chiffres 342 au nombre, on part de la fin, puis on ajoute chaque chiffre,
multiplié par la puissance de 10 adéquate :

2 * 1
+ 4 * 10
+ 2 * 10 * 10

soit :

2
+ 40
+ 300

79
Programmation en Python

ce qui fait bien 342.

14.1.3 La base 16

En informatique, on se sert souvent de la base 16. Cest le même principe : on se sert des ńăchiffresăż de 0 à F (A vaut
10, B vaut 11, jusquà F qui vaut 15).
Ainsi, la suite DA2 peut être interprétée comme suit :

2 * 1
+ 10 * 16
+ 13 * 16 * 16

soit :

2
+ 160
+ 3328

soit 3746.
On appelle aussi la base 16 la base hexadécimale, ou hexa en abrégé.

14.1.4 La base 2

La base 2, cest pareil, mais avec deux ńăchiffresăż : 0 et 1.


Ainsi, la suite 110 peut être interprétée comme suit :

0 * 1
+ 1 * 2
+ 1 * 2 * 2

soit :

0
+ 2
+ 4

soit 6.

14.1.5 Bits et octets

— un bit (bit en anglais) cest la valeur 1 ou 0 ;


— un octet (byte en anglais) cest une suite de 8 bits.

80 Chapitre 14. Chapitre 14 - Données binaires et fichiers


Programmation en Python

14.1.6 À retenir

Ces paquets de 8 ne veulent rien dire en eux-mêmes. Ils nont de sens que dans le cadre dune convention.
Par exemple, loctet 10100100 peut être un nombre écrit en binaire (164 en loccurrence), mais peut avoir une toute autre
signification.
Le nombre de valeurs possible augmente très rapidement avec le nombre doctets :
— 1 octet, cest 255 valeurs possibles (2 ** 8) ;
— 2 octets, cest 65.536 valeurs possibles (2 ** 16) ;
— 4 octets, cest [Link] valeurs possibles (2 ** 32).

14.1.7 Bases en Python

On se sert des préfixes 0b et 0x pour noter les nombres en base binaire ou hexadécimale respectivement :

print(0b1110)
# affiche: 6

print(0xDA2)
# affiche: 3490

14.1.8 Poids des bits

Regardez lexemple suivant :

x = 0b0010010 # 18
y = 0b0010011 # 19
z = 0b1010010 # 82

Notez que le premier bit est plus ńăfortăż que le dernier. On passe de 18 à 82 quand le premier bit passe de 0 à 1. À
linverse, on passe seulement de 18 à 19 quand le dernier bit passe de 0 à 1. On dit quon a utilisé un mode Petit-boutisme
(ńălittle endianăż en Anglais).
Voir aussi :
La page wikipedia consacée au boutisme.

14.1.9 Manipuler des octets en Python

On peut construire des listes doctets en utilisant bytearray et une liste de nombres :

data = bytearray(
[0b1100001,
0b1100010,
0b1100011
]
)

# equivalent:
data = bytearray([97, 98, 99])

(suite sur la page suivante)

14.1. Données binaires 81


Programmation en Python

(suite de la page précédente)


# equivalent aussi:
data = bytearray([0x61, 0x62, 0x63]

14.1.10 Texte

On peut aussi interpréter les octets comme du texte : Cest la table ASCII.

La table se lit ainsi : si on veut connaître la suite de 0 et de 1 qui correspond à B, on lit les 3 premiers bits de haut en
bas sur la colonne 100, puis les 4 bits sur la ligne 0010. Du coup B sécrit en 7 bits 1000010, soit 66 en décimal, et 42
en hexadécimal.

14.1.11 ASCII - remarques

— Cest vieux, 1960 !


— Le A est pour American.
— Ça sert à envoyer du texte vers des terminaux doù les ńăcaractèresăż non-imprimables dans la liste.
— Mais cest une convention très utilisée.
— Un message de 4 lettres ASCII sera souvent envoyé comme 4 octets (même si seulement 28 bits sont néces-
saires).

82 Chapitre 14. Chapitre 14 - Données binaires et fichiers


Programmation en Python

14.1.12 Utiliser ASCII en Python

Avec chr et ord :

x = chr(0x42)
print(x)
# affiche: B

x = ord('B')
print(x)
# affiche: 66

14.1.13 Affichage des bytearrays en Python

Python utilise ASCII pour afficher les bytearrays si les caractères sont ńăimprimablesăż :

data = bytearray([97, 98, 99])


print(data)
# affiche: bytearray(b"abc")

Note : Notez que Python rajoute quelque chose qui ressemble à un appel de fonction lorsquil affiche le bytearray : ce
nest pas un vrai appel de fonction.

Et \x pour laffichage en hexa si les caractères ne sont pas imprimables :

data = bytearray([7, 69, 76, 70])


print(data)
# affiche: bytearray(b"\x07ELF")

Notez bien que ce quaffiche Python nest quune interpétation dune séquence doctets.

14.1.14 Types

La variable b"abc" est une ńăchaîne doctetsăż, de même que "abc" est une ńăchaîne de caractèresăż.
Python appelle ces types bytes et str :

print(type("abc"))
# affiche: str

print(type(b"abc"))
# affiche: bytes

14.1. Données binaires 83


Programmation en Python

14.1.15 bytes et bytearray

De la même manière quon ne peut pas modifier un caractère à lintérieur dune string, on ne peut pas modifier un bit, ou
un octet dans une variable de type bytes :

a = "foo"
# a[0] = "f" => TypeError: 'str' object does not support item assignment

b = b"foo"
# b[0] = 1 => TypeError: 'bytes' object does not support item assignment

Par contre, on peut modifier un bytearray :

b = bytearray(b"foo")
b[0] = 103
print(b)
# affiche: bytearray(b"goo")

14.1.16 Conversion bytes <-> texte

Avec encode() et decode() :

text = "chaise"
encodé = [Link]("ascii")
print(encodé)
# affiche: b"chaise"

bytes = b"table"
décodé = [Link]("ascii")
print(décodé)
# affiche: b"table"

Notez que dans le deuxième exemple, on est bien en train de ńădécoderăż un paquet de 0 et de 1. Il peut sécrire ainsi :

bytes = b"\x74\x61\x62\x6c\x65"
décodé = [Link]("ascii")
print(décodé)
# affiche: table

14.1.17 Plus loin que lASCII

Vous avez sûrement remarquer quil ny a pas de caractères accentués dans ASCII. Du coup, il existe dautres conventions
quon appelle ńăencodageăż.
On peut spécifier lencodage quand on appelle la méthode decode() :

# latin-1: utilisé sur certains vieux sites


data = bytearray([233])
lettre = [Link]('latin-1')
print(lettre)
# affiche: 'é'

(suite sur la page suivante)

84 Chapitre 14. Chapitre 14 - Données binaires et fichiers


Programmation en Python

(suite de la page précédente)


# cp850: dans l'invite de commande Windows
data = bytearray([233])
lettre = [Link]('cp850')
print(lettre)
# affiche: 'Ú'

Notez que la même suite doctets a donné des résultats différents en fonction de lencodage !

14.1.18 Unicode

LUnicode, cest deux choses :


1. Une table qui associe un ńăcodepointăż à chaque caractère ;
2. Un encodage particulier, lUTF-8, qui permet de convertir une suite doctets en suite de codepoint et donc de
caractères.

14.1.19 UTF-8 en pratique

Dabord, UTF-8 est rétro-compatible avec ASCII :

encodé = "abc".encode("utf-8")
print(encodé)
# affiche: b'abc'

Ensuite, certains caractères (comme é) sont représentés par 2 octets :

encodé = "café".encode("utf-8")
print(encodé)
# affiche: b'caf\xc3\xa9"

Enfin, certains caractères (comme les emojis) sont représentés par 3 voire plus octets.

Avertissement : Toutes les séquences doctets ne sont pas forcément valides quand on veut les décoder en UTF-8.

14.1.20 Conséquences

— On peut représenter tout type de texte avec UTF-8 (latin, chinois, coréen, langues disparues, ).
— On ne peut pas accéder à la n-ième lettre directement dans une chaîne encodée en UTF-8, il faut parcourir lettre
par lettre (ce qui en pratique est rarement un problème).

14.1. Données binaires 85


Programmation en Python

14.2 Fichiers

14.2.1 Ouvrir un fichier en lecture

Fichiers ńătextesăż et fichiers ńăbinairesăż

Cela vous est peut-être déjà arrivé : Imaginons que vous ayez dans votre répertoire courant un code source python dans
mon_script.py et un pdf dans [Link].
Vous pourrez ouvrir mon_script.py dans un éditeur de texte, mais pas [Link], ou alors ça affichera nimporte
quoi.
En Python, on utilise la fonction native open(), en passant en argument le chemin du fichier.
Selon que lon veuille accéder au texte dans le fichier ou aux données binaires qui sont à lintérieur, on utilisera largument
"r" ou "rb" (r comme read, et b comme binary)
Enfin, open() renvoie un ńăfile-objetăż, quon note souvent f, qui contient une méthode read() pour lire le contenu
du fichier.
En pratique, voici ce que cela donne :

f = open("mon_script.py", "r")
code = [Link]()
print(code)
# affiche le code présent dans le fichier mon_script.py

f = open("[Link]", "rb")
données = [Link]()
# données est maintenant une grosse suite
# d'octets

f = open("[Link]", "r")
[Link]()
# Erreur: UnicodeDecodeError: 'utf-8' codec can't
# decode byte 0xd0 in position 10

Comme on doit utilisé loption rb pour lire le pdf, on dit parfois que le fichier pdf est un fichier ńăbinaireăż, par
opposition avec mon_script.py qui est un fichier ńătexteăż.
Ça na pas vraiment de sens : les deux fichiers sont stockés sur votre ordinateur comme des suites doctets, indépendam-
ment de leur contenu.
Il se trouve que lun des deux contient une suite doctets qui est décodable en tant que string. En fait, sous le capot,
la suite doctets renvoyée dans le premier example a été décodée avec lencodage par défaut de votre système. On peut
dailleurs passer lencodage en argument à open() :

f = open("vieux_texte_en_latin_1.txt", "r", encoding="latin-1")


texte = [Link]()

86 Chapitre 14. Chapitre 14 - Données binaires et fichiers


Programmation en Python

14.2.2 Ouvrir un fichier en écriture

On peut aussi écrire dans un fichier, toujours avec open(), mais cette fois-ci avec la méthode write() du file-objet.
On peut écrire du texte avec loption "w" et une chaîne de caractères :

f = open("mon_script.py", "w")
[Link]("Nouveau contenu!")

Et écrire directement des données binaires avec "wb" et une suite doctets

f = open("[Link]", "wb")
[Link](b"\x0c\x1f...")

Encore une fois, sous le capot, la chaîne de caractères sera encodée par Python avant dêtre écrite dans le fichier texte.

14.2.3 Fermeture des file-objets

Notez quil est impératif de fermer les fichiers que vous ouvrez, que ce soit en lecture ou en écriture, en appelant la
méthode close() :

f = open("mon_poé[Link]", "w")
[Link](premier_vers)
[Link](deuxième_vers)
[Link]()

14.2.4 Conseils

— On utilise souvent le binaire pour échanger entre Python et le monde extérieur.


— Tout texte a un encodage, et il vous faut connaître cet encodage pour travailler avec.
— Si vous avez le choix, utilisez UTF-8.

14.2. Fichiers 87
Programmation en Python

88 Chapitre 14. Chapitre 14 - Données binaires et fichiers


CHAPITRE 15

Chapitre 15 - Linterpréteur interactif

15.1 Démarrage

Jusquici, on a toujours lancé la commande Python avec python suivi du nom dun fichier source.
Il est égalemnet possible de lancer la commande python3 sans argument.
Dans ce cas, on se retrouve avec une autre invite de commandes :

$ python3
Python 3.7.1 (default, Oct 22 2018, 10:41:28)
[GCC 8.2.1 20180831] on linux
Type "help", "credits" or "license" for more information.
>>>

89
Programmation en Python

15.2 Deux invites de commandes

Notez les trois chevrons : >>>. Cela vous permet de différencier linvite de commandes du système dexploitation de
celle de Python.
— Système dexploitation -> Python : taper python3 (sans arguments).
— Python -> Système dexploitation : taper quit().

15.3 Fonctionnement de linterpréteur

Linterpréteur fonctionne dans une boucle :


1. Lire le code qui a été tapé (soit une ligne, soit une succession de blocs) ;
2. Évaluation du code qui a été entré ;
3. Affichage de la valeur le cas échéant ;
4. Retour au début.
(En anglais, on dit ńăREPLăż pour ńăread/eval/print/loopăż)
Example dune session interactive :

>>> a = 42
>>> a
42
>>> b = 4
>>> a + b
46

Notez que si la variable est None, linterpréteur naffiche rien :

>>> def ne_fait_rien():


pass
>>> résultat = ne_fait_rien()
>>> résultat
>>> résultat is None
True

15.4 Interpréteur interactif et imports

Recréons un fichier [Link] contenant :

# dans [Link]
salutation = "Bonjour,"
def dire_bonjour(nom):
print(salutation, nom)

On peut démarrer un interpréteur interactif dans le répertoire contenant le fichier bonjour`.py, et ńăjouerăż avec les
attributs du module bonjour :

90 Chapitre 15. Chapitre 15 - Linterpréteur interactif


Programmation en Python

>>> import bonjour


>>> bonjour.dire_bonjour("Bob")
Bonjour, Bob

>>> [Link] = "Hello,"


>>> bonjour.dire_bonjour("Bob")
Hello, Bob

Avertissement : Si le contenu de [Link] change, il faut relancer linterpréteur interactif et refaire limport.

15.4. Interpréteur interactif et imports 91


Programmation en Python

92 Chapitre 15. Chapitre 15 - Linterpréteur interactif


CHAPITRE 16

Chapitre 16 - Héritage

16.1 Rappel : composition

Dans un chapitre précédent, on a parlé de composition qui décrit une classe à lintérieur dune autre classe.
Pour rappel :

class Chat:
def __init__(self, nom):
[Link] = nom

def ronronne(self):
print([Link], 'fait: "prrrrr"')

def caresse(self):
[Link]()

class Enfant:
def __init__(self, prénom, chat):
[Link] = chat

def console(self):
[Link]()

93
Programmation en Python

16.2 Vocabulaire

Ici on va parler dhéritage, qui décrit une autre relation entre classes, appelée parfois un peu abusivement ńăpartage de
codeăż.
Pour indiquer quune classe B hérite dune classe A, on écrit A dans des parenthèses au moment de déclarer la classe B :

class A:
...

class B(A):
...

Les trois formulations suivantes sont souvent employées :


— A est la classe parente de B.
— B hérite de A.
— B est une classe fille de A.

16.3 Utilisation

Si une méthode nest pas trouvée dans la classe courante, Python ira la chercher dans la classe parente :

class A:
def méthode_dans_a(self):
print("dans A")

class B(A):
def méthode_dans_b(self):
print("dans B")

b = B()
b.méthode_dans_b()
# Affiche: 'dans B', comme d'habitude

b.méthode_dans_a()
# Affiche: 'dans A'

16.4 Ordre de résolution

Sil y a plusieurs classes parentes, Python les remonte toutes une à une. On dit aussi quil y a une hiérarchie de classes :

class A:
def méthode_dans_a(self):
print("dans A")

class B(A):
def méthode_dans_b(self):
print("dans B")

(suite sur la page suivante)

94 Chapitre 16. Chapitre 16 - Héritage


Programmation en Python

(suite de la page précédente)


class C(B):
def méthode_dans_c(self):
print("dans C")

c = C()
c.méthode_dans_a()
# affiche: 'dans A'

16.5 Avec __init__

La résolution fonctionne pour toutes les méthodes, y compris __init__ :

class A:
def __init__(self):
print("initialisation de A")

class B(A):
...

b = B()
# affiche: "initialisation de A"

16.6 Attributs

Même mécanisme pour les attributs :

class A:
def __init__(self):
self.attribut_de_a = 42

class B(A):
...

b = B()
print(b.attribut_de_a)
# affiche: 42

16.7 Surcharge

On peut aussi surcharger la méthode de la classe parente dans la classe fille :

class A:
def une_méthode(self):
print("je viens de la classe A")

class B(A):
(suite sur la page suivante)

16.5. Avec __init__ 95


Programmation en Python

(suite de la page précédente)


def une_méthode(self):
print("je viens de la classe B")

b = B()
b.une_méthode()
# affiche: "je viens de la classe B'

16.8 super()

On peut utiliser super() pour chercher explicitement une méthode dans la classe parente :

class A:
def une_méthode(self):
print("je viens de la classe A")

class B(A):
def une_méthode(self):
super().une_méthode()
print("je viens de la classe B")

b = B()
b.une_méthode()
# affiche:
# je viens de la classe A
# je viens de la classe B

16.9 super() et __init__

Erreur très courante :

class A:
def __init__(self):
self.attribut_de_a = "bonjour"

class B(A):
def __init__(self):
self.attribut_de_b = 42

b = B()
print(b.attribut_de_b)
# affiche: 42
print(b.attribut_de_a)
# erreur: AttributeError

On a surchargé A.__init__(), du coup linitialisation de A na jamais été faite.


La plupart du temps, si A et B ont des constructeurs, on appellera super().__init__() dans le constructeur de la
classe fille :

96 Chapitre 16. Chapitre 16 - Héritage


Programmation en Python

class A:
def __init__(self):
self.attribut_de_a = "bonjour"

class B(A):
def __init__(self):
super().__init__()
self.attribut_de_b = 42

b = B()
print(b.attribut_de_b)
# affiche: 42
print(b.attribut_de_a)
# affiche: "bonjour"

16.9. super() et __init__ 97


Programmation en Python

98 Chapitre 16. Chapitre 16 - Héritage


CHAPITRE 17

Chapitre 17 - Décorateurs

17.1 Jouons avec les fonctions

17.1.1 Introduction

Reprenons ce quon a vu jusquici.


Dune part, on peut créer des variables en assignant des valeurs à celles-ci :

# Création d'une variable `x` avec la valeur 4


x = 4

Dautre part, on peut définir et appeler des fonctions :

# Définition de la fonction:
def dire_bonjour(nom):
print("Bonjour " + nom)

# Appel
dire_bonjour("Max")

# Affiche: "Bonjour Max"

99
Programmation en Python

17.1.2 Fonctions en tant que variables

Il se trouve quen Python, on peut assigner des fonctions à des variables. Cest différent dassigner le résultat de lappel à
une fonction à une variable, et ça permet de retarder lappel :

# Définition d'une fonction `dire_bonjour_en_français`


def dire_bonjour_en_français(nom):
print("Bonjour " + nom)

# Définition d'une fonction `dire_bonjour_en_anglais`


def dire_bonjour_en_anglais(nom):
print("Hello " + nom)

# Assigne une fonction à la variable - aucune fonction


# n'est appelée à ce stade.
ma_fonction_qui_dit_bonjour = dire_bonjour_en_français

# Appel de la fonction (retardé)


ma_fonction_qui_dit_bonjour("Max")

# Affiche: Bonjour Max

De façon cruciale, notez que lon na pas mis de parenthèses à droite lorsquon a créé la variable
ma_fonction_qui_dit_bonjour.
On peut donc dire que lorsquon définit une fonction avec def ma_fonction() et un corps, il y a en réalité deux
étapes :
1. Python stocke le corps de la fonction quelque part ;
2. Il assigne le corps de celle-ci à une variable dont le nom est ma_fonction.
En Python, il est assez fréquent dutiliser un code tel que celui-ci, souvent avec un dictionnaire :

fonctions_connues = {
"français": dire_bonjour_en_français,
"anglais": dire_bonjour_en_anglais,
}

# Ici on stocke la langue parlée par l'utilisateur


# et son prénom
langue_parlée = ...
prénom = ....

if langue_parlée in fonctions_connues:
fonction = fonctions_connues[langue_parlée]
fonction(prénom)

100 Chapitre 17. Chapitre 17 - Décorateurs


Programmation en Python

17.1.3 Fonctions en tant quargument dautres fonctions

On a vu en début de chapitre quon peut assigner des fonctions à des variables.


Du coup, rien nempêche de passer des fonctions en argument dautres fonctions.
Par exemple :

def appelle_deux_fois(f):
f()
f()

def crier():
print("Aline !")

appelle_deux_fois(crier)

# affiche:
# Aline !
# Aline !

17.1.4 Fonctions imbriquées

On peut aussi définir une fonction dans une autre fonction :

def affiche_message(message):
def affiche():
print(message)
affiche()

affiche_message("Bonjour")
# affiche: Bonjour

Deux notes importantes :


Premièrement, la fonction affiche() qui est imbriquées dans affiche_message() nest pas accessible à lextérieur
de la fonction qui la contient. En dautres termes, ce code ne fonctionne pas :

def affiche_message(message):
def affiche():
print(message)

affiche()
# NameError: 'affiche' is not defined

Cest un mécanisme similaire aux portées des variables vu précédemment.


Deuxièment, la fonction affiche() à lintérieur de affiche_message() a accès à largument message de la fonction
affiche_message(). On appelle ça une ńăclosureăż.

17.1. Jouons avec les fonctions 101


Programmation en Python

17.1.5 Fonctions retournant des fonctions

En réalité, on combine souvent les closures avec des fonctions qui retournent dautres fonctions :

def fabrique_fonction_qui_additionne(n):
def fonction_résultat(x):
return x + n
return fonction_résultat

additionne_2 = fabrique_fonction_qui_additionne(2)
y = additionne_2(5)
print(y)
# affiche: 7

17.1.6 Un autre paradigme

Le fait quon puisse traiter les fonctions comme nimporte quelle autre valeur (cest-à-dire les assigner à des variables,
les passer en argument et les retourner), est caractéristique des langages dits ńăfonctionnelsăż. Python est donc à la fois
un langage impératif, objet et fonctionnel. On dit que cest un langage multi-paradigmes.

17.2 Décorateurs

17.2.1 Définition

Un décorateur est une fonction qui enveloppe une autre fonction.


On place le nom du décorateur avec une arobase (@) au-dessus de la fonction décorée :

def mon_décorateur(fonction):
def fonction_retournée():
# fait quelque chose avec l'argument `fonction`, par exemple
# l'appeler avec un argument:
fonction(42)
return fonction_retournée

@mon_décorateur
def ma_fonction_décorée(un_argument):
fais_un_truc_avec(un_argument)

Les deux dernières lignes sont équivalentes à :

def ma_fonction_décorée(un_argument):
fais_un_truc_avec(un_argument)

ma_fonction_décorée = mon_décorateur(ma_fonction_décorée)

102 Chapitre 17. Chapitre 17 - Décorateurs


Programmation en Python

17.2.2 Exemples de décorateurs

On peut faire un décorateur qui nous empêche dappeler une fonction sous certaines conditions :

def pas_pendant_la_nuit(fonction):
def résultat():
if il_fait_nuit:
print("chut")
else:
fonction()
return résultat

@pas_pendant_la_nuit
def dire_bonjour():
print("bonjour")

il_fait_nuit = True
dire_bonjour()
# affiche: "chut"

17.2.3 Décorateur prenant des arguments

On peut aussi avoir des arguments passés aux décorateurs. Dans ce cas, on a besoin de trois fonctions imbriquées. En
effet, il nous faut une fonction pour traiter largument message et une autre pour traiter largument fonction :

def affiche_message_avant_appel(message):
def décorateur(fonction):
def résultat():
print(message)
fonction()
return résultat
return décorateur

@affiche_message_avant_appel("dire_bonjour est appelée")


def dire_bonjour():
print("bonjour")

dire_bonjour()
# affiche:
# dire_bonjour est appelée
# bonjour

17.2. Décorateurs 103


Programmation en Python

104 Chapitre 17. Chapitre 17 - Décorateurs


CHAPITRE 18

Chapitre 18 - Exceptions

On a souvent montré des exemples de code qui provoquaient des erreurs au cours des chapitres précédents. Il est temps
maintenant de se pencher davantage sur celles-ci.

18.1 Pile dappels

Reprenons un exemple de code qui provoque une erreur, par exemple en essayant de diviser par zéro :

def mauvaise_fonction():
return 1 / 0

def fonction_intermédiaire():
mauvaise_fonction()

def fonction_principale():
fonction_intermédiaire()

fonction_principale()

Si on lance ce code, voilà ce quon obtient :

Traceback (most recent call last):


File "mauvaises_maths.py", line 13, in <module>
fonction_principale()
File "mauvaises_maths.py", line 10, in fonction_principale
fonction_intermédiaire()
File "mauvaises_maths.py", line 6, in fonction_intermédiaire
mauvaise_fonction()
File "mauvaises_maths.py", line 2, in mauvaise_fonction
return 1 / 0
ZeroDivisionError: division by zero

105
Programmation en Python

Ceci est une pile dappels. Elle permet de voir exactement par quelles fonctions on est passé et dans quel ordre. Elle se
lit de haut en bas :
— on a appelé fonction_principale() ;
— cette fonction a à son tour appelé fonction_intermédiaire() ;
— fonction_intermédiaire() a appelé mauvaise_fonction() ;
— mauvaise_fonction() a levé une exception.
Notez que chaque élément de la pile comprend :
— le nom de la fonction ;
— le chemin du module la contenant ;
— le numéro et la ligne précise du code qui a été appelé .
Il est important de bien lire les piles dappels quand on cherche à comprendre doù vient une exception.
Après la pile dappels, on a le nom de lexception et sa description.

18.2 Exceptions natives

Les exceptions sont toujours des instances de classes, et les classes dexceptions héritent toujours de la classe
BaseException.
Le nom de lexception est en réalité le nom de la classe, ici lexception levée par la ligne return 1 / 0 est une instance
de la classe ZeroDivisionError.
Cette exception fait partie des nombreuses exceptions prédéfinies en Python. Ensemble, elles forment une hiérarchie
dexceptions dont voici un extrait :

BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- Exception
+-- ArithmeticError
| +-- ZeroDivisionError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- OSError
| +-- FileNotFoundError
+-- TypeError
+-- ValueError

18.2.1 IndexError et KeyError

IndexError est levée quand on essaye daccéder à un index trop grand dans une liste :

ma_liste = ["pomme"]
ma_liste[2] = "abricot"

# IndexError: list assignment index out of range

KeyError est levée quand on essaye daccéder à une clé qui nexiste pas dans un dictionnaire :

scores = { "Alice" : 10 }
score_de_bob = scores["Bob"]
(suite sur la page suivante)

106 Chapitre 18. Chapitre 18 - Exceptions


Programmation en Python

(suite de la page précédente)

# KeyError: 'Bob'

Notez que la description de KeyError est la valeur de la clé manquante.

18.2.2 ValueError

ValueError est levée (entre autres) quand on tente une mauvaise conversion :

entrée_utilisateur = "pas un nombre"


valeur = int(entrée_utilisateur)

18.2.3 KeyboardInterrupt

KeyboardInterrupt est levée quand on fait ctrl-c.

18.2.4 FileNotFoundError

FileNotFoundError est levée quand on essaye douvrir, en lecture, un fichier qui nexiste pas :

with open("[Link]", "r") as f:


contenu = [Link]()

18.3 Gestion des exceptions

18.3.1 Bloc try/except

On peut gérer (ou attraper) une exception en utilisant un bloc try/except et le nom dune classe dexception :

try:
a = 1 / 0
except ZeroDivisionError:
print("Quelqu'un a essayé de diviser par zéro!")

# affiche: Quelqu'un a essayé de diviser par zéro!

À noter : Le bloc dans try sinterrompt dès quune exception est levée, et on ne passe dans le bloc except que si une
exception est effectivement levée.

x = 14
y = 0
try:
z = x / y
print("z vaut", z)
except ZeroDivisionError:
print("Quelqu'un a essayé de diviser par zéro!")

# affiche: Quelqu'un a essayé de diviser par zéro!

18.3. Gestion des exceptions 107


Programmation en Python

Notez que la ligne print("z vaut", z) na pas été exécutée.


Autre exemple :

x = 14
y = 2
try:
z = x / y
print("z vaut", z)
except ZeroDivisionError:
print("Quelqu'un a essayé de diviser par zéro!")

# affiche: 'z vaut 7.0'

Notez que la ligne print("Quelqu'un a essayé de diviser par zéro!") na pas été exécutée.

18.3.2 Gestion de plusieurs exceptions

Le mot après except doit être celui dune classe, et lexception nest gérée que si sa classe est égale ou une fille de
celle-ci.
Par exemple, ceci fonctionne car ZeroDivisionError est bien une fille de la classe ArithmeticError :

x = 14
y = 0
try:
z = x / y
print("z vaut", z)
except ArithmeticError:
print("Quelqu'un a essayé une opération impossible")

On peut aussi mettre plusieurs blocs de except :

try:
tente_un_truc_risqué()
except ZeroDivisionError:
print("raté : division par zéro!")
except FileNotFoundError:
print("raté : fichier non trouvé")

Ou gérer des exceptions de classes différentes avec le même bloc :

try:
tente_un_truc_risqué()
except (ZeroDivisionError, FileNotFoundError)
print("raté!")

108 Chapitre 18. Chapitre 18 - Exceptions


Programmation en Python

18.3.3 Accéder à la valeur de lexception

On peut récupérer linstance de lexception levée avec le mot-clé as :

try:
ouvrir_fichier()
except FileNotFoundError as e:
print("le fichier: ", [Link], "n'existe pas")

Ici on utilise lattribut filename de la classe FileNotFoundError pour afficher un message derreur.

18.4 Levée dexceptions

18.4.1 raise

On peut lever explicitement une exception en appelant le mot-clé raise suivi dune instance dune classe.
Par exemple en utilisant une exception native :

def dire_bonjour(prénom):
if not prénom:
raise ValueError("prénom vide")

18.4.2 Définition dexceptions à la carte

On peut ré-utiliser les exceptions natives, ou définir sa propre classe :

class OpérationImpossible(Exception):
pass

def ma_fonction():
if cas_impossible:
raise OpérationImpossible()

18.4.3 Gérer puis re-lever lexception géré

Parfois il est utile de re-lever lexception quon vient de gérer.


Dans ce cas, on utilise raise sans argument :

try:
tente_un_truc_risqué()
except ArithmeticError:
...
raise

18.4. Levée dexceptions 109


Programmation en Python

18.5 Else et finally

18.5.1 else

Si on rajoute un bloc else après le except, le bloc nest éxécuté que si aucune exception na été levée :

try:
tente_un_truc_risqué()
except (ZeroDivisionError, FileNotFoundError):
print("raté")
else:
print("ouf, ça a marché")

18.5.2 finally

Si on rajoute un bloc finally après le except, le bloc est exécuté dans tous les cas, quune exception ait été levé ou
non. On sen sert souvent pour ńăannulerăż du code qui aurait été utilisé dans le bloc try :

personnage = Personnage()
try:
personnage.entre_en_scène()
personnage.tente_un_truc_risqué()
except ZeroDivisionError:
print("raté")
finally:
personnage.quitte_la_scène()

Si dans le bloc try une exception différente de ZeroDivisionError est levée, on passera quand même dans le bloc
finally, puis lexception sera levée à nouveau.
TODO : exemple plus complet

110 Chapitre 18. Chapitre 18 - Exceptions


CHAPITRE 19

Chapitre 19 - Objets

On a déjà parlé de programmation orientée objet en Python, mais pour linstant, on a vu que des classes et des instances.
Or, le concept dobjet existe bel et bien en Python, et il est plus que temps de vous le présenter.
Mais avant, il faut faire un petit détour par les attributs et méthodes de classes.

19.1 Attributs et instances de classe

19.1.1 Rappels

Voici un exemple de classe qui contient une méthode :

class MaClasse
def ma_méthode(self):
print(self.mon_attribut)

Le bloc indenté en-dessous du mot-clé class sappelle le corps de la classe. Et les méthodes sont définies avec le
mot-clé def dans le corps de la classe.
On dit que ce sont des méthodes dinstance parce quil faut créer une instance pour pouvoir les appeler :

mon_instance = MaClasse()
mon_instance.ma_méthode()

111
Programmation en Python

19.1.2 Attributs de classes

On peut également déclarer des variables dans le corps dune classe.


On crée ainsi des attributs de classe :

class MaClasse:
mon_attribut_de_classe = 42

Ici mon_attribut_de_classe existe à la fois dans les instances de MaClasse et dans la classe elle-même :

print(MaClasse.mon_attribut_de_classe)
# affiche: 42
mon_instance = MaClasse()
print(mon_instance.mon_attribut_de_classe)
# affiche: 42

Un point important est que les attributs de classe sont partagés entre toutes les instances. Voici un exemple dutilisation
possible :

class Voiture:
nombre_total_de_voitures_fabriquées = 0

def __init__(self, marque, couleur):


print("Construction d'une", marque, couleur)
Voiture.nombre_total_de_voitures_fabriquées += 1

ferrari_1 = Voiture("Ferrari", "rouge")


mercedes_1 = Voiture("Mercedes, "noire")
ferrari_2 = Voiture("Ferrari", "rouge")
print("total:", Voiture.nombre_total_de_voitures_fabriquées)
# affiche:
# Construction d'une Ferrari rouge
# Construction d'une Mercedes noire
# Construction d'une Ferrari rouge
# total: 3

Notez que pour changer lattribut de classe depuis une méthode, (comme dans la méthode __init__ ci-dessus) on
utilise le nom de la classe directement, et non pas self.

19.1.3 Méthodes de classes

On peut aussi définir des méthodes de classes avec le décorateur classmethod.


Dans ce cas, le premier argument sappelle cls et prend la valeur de la classe elle-même. Pour poursuivre sur notre
exemple :

class Voiture:
nombre_total_de_voitures_fabriquées = 0

def __init__(self, marque, couleur):


print("Construction d'une", marque, couleur)
Voiture.nombre_total_de_voitures_fabriquées += 1
(suite sur la page suivante)

112 Chapitre 19. Chapitre 19 - Objets


Programmation en Python

(suite de la page précédente)

@classmethod
def fabrique_ferrari(cls):
return cls("ferrari", "rouge")

ferrari = Voiture.fabrique_ferrari()

Détaillons ce quil se passe sur la dernière ligne : à gauche du signe égal, il y a une variable, et à droite une expression
(Voiture.fabrique_ferrari())
Lexpression est constitué dune classe à gauche du point (Voiture), et dun attribut à droite du point
fabrique_ferrari, suivi de parenthèses.
Comme fabrique_ferrari est une méthode de classe, on va appeler la méthode de classe fabrique_ferrari en
lui passant la classe courante en argument.
On arrive ainsi dans le corps de la méthode de classe fabrique_ferrari, et cls vaut la classe Voiture.
Finalement, on évalue lexpression cls("ferrari", rouge") en remplaçant cls par sa valeur, ce qui donne
Voiture("ferrari", "rouge") qui correspond bien à ce quon obtient : Une instance de la classe Voiture.

19.2 Objets

En fait, tout ce quon manipule en Python est un objet. Et tous les objets sont toujours des instances dune classe. On
peut accéder à la classe qui a servi à instancier un objet avec la fonction type, par exemple :

class MaClasse:
pass

mon_instance = MaClasse()
print(type(mon_instance))
# affiche:
# <class '__main__.MaClasse'>

Mais aussi :

print(type(2))
# affiche: int

print(type("bonjour"))
# affiche: str

Donc en Python, les entiers sont des instances de la classe int, et les strings des instances de la classe str.
Ainsi, vous pouvez voir lexpression x = str(y) de deux façons :
— Soit on appelle la fonction native str pour convertir y en string.
— Soit on crée une nouvelle instance de la classe str en appelant le constructeur de la classe str avec y en
argument.
Notez que ça ne sarrète pas là :

def ma_fonction():
pass
(suite sur la page suivante)

19.2. Objets 113


Programmation en Python

(suite de la page précédente)

print(type(ma_fonction))
# affiche: function

class MaClasse:
def ma_méthode(self):
pass

mon_instance = MaClasse()
print(type(mon_instance.ma_méthode))
# affiche: method

import sys
print(type(sys))
# affiche: module

Et même :

print(type(MaClasse))
# affiche: type

print(type(type))
# affiche: type

Et oui, les classes elles-mêmes sont des instances de classe ! (de la classe type)
Du coup en Python, le terme objet désigne toujours une instance de classe, même None est une instance dune classe
(elle sappelle NoneType).

19.2.1 Ordre de résolution

Il est temps de revenir sur lévaluation des expressions impliquant des attributs.
On a vu trois systèmes différents :
Appeler une fonction définie dans un module :

import mon_module
mon_module.ma_fonction()

Appeler une méthode dinstance définie dans une classe :

mon_instance = MaClasse()
mon_instance.ma_méthode()

Appeler une méthode de classe définie dans une classe :

MaClasse.ma_méthod_de_classe()

Daprès ce quon a vu dans la section précédente, on sait maintenant que dans tous les cas, à gauche du point se situe un
objet, et que tous les objets sont des instances dune classe (appelé le ńătypeăż de lobjet).
Pour évaluer lexpression mon_objet.mon_attribut, où mon_objet est une instance de mon_type, Python cherche
toujours lattribut dans deux endroits :
— dabord en tant quattribut de linstance mon_objet ;

114 Chapitre 19. Chapitre 19 - Objets


Programmation en Python

— ensuite, en tant quattribut de la classe mon_type.


La recherche se poursuit ainsi en suivant toutes les classe parentes de mon_type.
On peut voir ce mécanisme en action dans le code suivant :

class A:
def f1(self):
print("f1 dans A")

def f2(self):
print("f2")

class B(A):
@classmethod
def f3(cls):
print("f3")

def f1(self):
print("f1 dans B")

b = B()
b.f1()
b.f3()
b.f2()
# affiche:
# f1 dans B
# f3
# f2

19.2.2 Conclusion

Maintenant, vous devriez comprendre pourquoi on dit parfois quen Python, tout est objet.
Dans un prochain chapitre, on expliquera pourquoi, en plus de cela, on peut dire quen Python, tout est dictionnaire.

19.2. Objets 115

Vous aimerez peut-être aussi