0% ont trouvé ce document utile (0 vote)
217 vues103 pages

Programmer en Python_2024-25

Transféré par

linakrimzer
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)
217 vues103 pages

Programmer en Python_2024-25

Transféré par

linakrimzer
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
Vous êtes sur la page 1/ 103

Programmer en Python

Support de cours
Sup De Vinci – 2024/2025

Module 0

A propos de cette formation

n° 2

1
Votre formation - Programme
 Présentation de Python
 La mise en place d’une plateforme Python
 Les bases du langage
 Les fonctions
 Les modules et les packages
 Les classes
 L’héritage
 La gestion des exceptions
 Les collections : aspects avancés
 La bibliothèque standard
 La gestion de base de données

n° 5

n° 6

3
Module 1
Présentation de Python

n° 7

Historique
 Création en 1989 au Pays-Bas par Guido Van Rossum.
 Première version publique (0.9.0) en 1991.
 Objectif :
 Améliorer et étendre les fonctionnalités du Bourne Shell, l’interface utilisateur
des systèmes Unix de l’époque.
 Version 2.0 en 2000
 Version 3.0 en 2008
 Dernière Version 3.12 octobre 2023
 La licence libre de Python, oscillant entre la GPL et la licence Apache est crée
en même temps que la Python Software Foundation
 Python Software Foundation License

n° 8

4
Cas d’utilisation
 Programmation système et réseau
 Création d’utilitaires complémentaires ou bien spécifique pour les OS
 DataCenter :
 Manipulation de données
 Programmation scientifique
 Calculs avancés, intelligence artificielle (tensorflow ...)
 Programmation Web
 Frameworks Web MVC (Django)
 Informatique embarquée
 Raspberry PI, Arduino, …
 Programmation graphique
 Applications de bureau, prototypage de jeux vidéos
 Education
 Apprentissage et mise en pratique de l’algorithmie

n° 9

Caractéristiques du langage
 Simple, concis et lisible
 Bibliothèque standard riche de fonctionnalités
 Multitude de bibliothèques complémentaires disponibles
 Communauté très étendue
 Multiplateforme
 Adapté aux systèmes d’exploitation
 Typage dynamique fort
 Possède plusieurs approches pour la structuration des programmes
 Impérative, fonctionnelle, objet, …

n° 10

5
Philosophie Python
 Simplicité d’écriture: le temps d’exécution n’est pas aussi important que le
temps nécessaire à l’écriture du code.
 pour accomplir une certaine tâche, il vous faut une journée pour écrire un
programme, qui s’exécute en une seconde.
 certains utilisateurs préféreront, pour accomplir la même tâche, avoir un
programme qui s’exécute en cinq minutes, mais qui s’écrit en une demi-heure.
 Quand la performance est devenue un problème, la communauté a amélioré
le langage.
 Basé sur la confiance et la bonne utilisation des développeurs :
 Pas de constante en python
 Une constante est une variable qu’on ne doit pas faire évoluer. Pour cela on va
simplement déclarer l’identifiant en majuscule.

n° 11

Le contenu de Python
 Un langage
 Avec une syntaxe simple
 Une grammaire étendue
 Des implémentations
 Pour faire « tourner » un programme Python !
o CPython (Implémentation de référence)
o Jython
o IronPython
 Une bibliothèque standard
 Elle offre les fonctionnalités de base du langage
 Des bibliothèques complémentaires
 Mises à disposition par la communauté
 Elles couvrent des besoins complémentaires à la bibliothèque standard

n° 12

6
Exécution d’un programme Python

Code
Source
Cache
Disque
Fichier .py

1. Lancement

Exécution
Byte
du
Code
programme
2. Compilation 3. Interprétation

Fichier .pyc

Python Virtual Machine (PVM)

n° 13

Module 2
Mise en place d’une plateforme
Python

n° 14

7
Installation de Python
 Installer une implémentation !
 Pour commencer, utiliser l’implémentation de référence (CPython) disponible
sur le site officiel : http://www.python.org
 Des versions pour Windows et MacOS sont disponibles
o Pour Linux, soit Python est déjà installé dans la version souhaitée, soit il faudra utiliser
le gestionnaire de logiciels de sa distribution
 L’installeur propose des options de personnalisation
 Emplacement d’installation
 Fonctionnalités à installer

n° 15

La console Python
 La console Python est un outil interactif permettant d’exécuter à la volée des
instructions de code
 A la manière d’un shell Unix !
 La commande python dans un terminal ou interpréteur de commande
permet de lancer la console
 L’instruction exit()permet d’en sortir

 Cet outil permet d’évaluer rapidement des portions de code


 La console est souvent directement intégrée dans les IDE pour Python

n° 16

8
Les librairies additionnelles
 Même si Python vient avec une bibliothèque standard très riche, il est parfois
nécessaire d’ajouter des bibliothèques supplémentaires pour couvrir des
besoins spécifiques
 2 options essentiellement :
 Installation avec PIP
 Installation à partir des sources
 Installation avec PIP
 Option la plus pratique
 Une installation de Python vient avec un utilitaire en ligne de commande
permettant de télécharger et d’installer des paquets Python

n° 17

Installation avec PIP


 Option la plus pratique
 Une installation de Python vient avec un utilitaire en ligne de commande
permettant de télécharger et d’installer des paquets Python : pip
 pip s’appui sur un référentiel accessible à l’adresse http://pypi.org pour
effectuer les téléchargements

 pip possède plusieurs commandes pour installer, désinstaller,


rechercher, lister les paquets

n° 18

9
Les commandes de PIP
 La commande pip --help donne la liste des commandes ainsi que des options
de pip.

 Parmi les principales, on notera :


 install: Pour installer un paquet
 uninstall: Pour désinstaller un paquet
 freeze: Pour afficher la liste des paquets installés dans un format « requirements »
o pip freeze > requirements.txt
• On dresse la liste des paquets installés, redirigée vers un fichier.
o pip install -r requirements.txt
• Permet, sur une autre machine par exemple, d’installer les paquets listés dans le fichier.

n° 19

Installation à partir des sources


 Certaines librairies Python sont livrées sous forme de code source dans des
archives compressée (format ZIP ou TAR.GZ)
 Leur installation se fait à partir de la ligne de commande, grâce à
l’interpréteur Python.
 Un fichier README est fréquemment fourni pour indiquer la procédure
d’installation.
 Mais la démarche est souvent la même !
 Le fichier setup.py permet la configuration et l’installation.

Python setup.py install

n° 20

10
Les environnements virtuels
 Les environnements virtuels de Python permettent de « cloner » une
installation de Python dans un dossier dédié.
 Il est ensuite possible d’y installer toutes les librairies nécessaires, sans
toucher à l’installation de base de l’interpréteur, évitant ainsi :
 De surcharger cette dernière d’une multitude de librairies ;
 De générer des conflits entre les librairies ;
 De mélanger les spécificités de différents projets.
 La création d’un environnement virtuel se fait en une seule commande. Elle
va créer un dossier dédié.

n° 21

Les environnements virtuels


 Une fois l’environnement virtuel créé, il est nécessaire de l’activer pour
pouvoir l’utiliser, le prompt change pour indiquer l’environnement actif.
 Sous Linux (ou macOS), le script activate se trouve dans le sous-répertoire bin/
Sous Windows, dans le sous-répertoire Scripts\.

 Sous macOS, il faut taper : source ./bin/activate

 La commande deactivate permet de désactiver un environnement virtuel,


quel que soit l’OS.

n° 22

11
Les IDEs pour Python
 Plusieurs environnement de développement intégré existent pour Python.
 Ils permettent de disposer de fonctionnalités essentielles pour tout développeur,
comme par exemple :
 L’assistance à la création de projet
 La coloration syntaxique du code
 L’assistance à la saisie du code
 Une console Python intégrée
 Un lancement facilité des programmes
 Un débogueur pour la mise au point des programmes
 Parmi les IDE les plus populaires, on trouve notamment :
 PyCharm
o Référence dans le domaine. Edition « Community » (Gratuite) et « Professional » (Commerciale)
o https://www.jetbrains.com/pycharm/
 PyDev
o Base Eclipse associé à un plugin pour la prise en charge de Python
o http://www.pydev.org
 Visual Studio Code
o Outil Microsoft multi-plateforme

n° 23

Module 3
Les bases du langage

n° 24

12
Syntaxe du langage
 Voici quelques principes énoncés par Guido van Rossum :
 Simple et intuitif
 Compréhensible, aussi simple à comprendre que de lire l’anglais
 Approprié pour les tâches quotidiennes
 Permettant des temps de développement courts

n° 25

Instructions et délimiteurs
 A la différence d’autres langages, Python n’utilise pas de caractère spécifique
pour délimiter les instructions de code.
 Une instruction étant un ordre simple que le langage doit exécuter
 Le saut de ligne suffit à terminer l’instruction courante
 Pas d’usage du « ; » comme en C, C++, Java, …
 Il est parfois nécessaire, par soucis de lisibilité, d’écrire des instructions sur
plusieurs lignes. Dans ce cas, on utilisera le « \ » pour indiquer que
l’instruction courante se poursuit sur la ligne suivante.

print ("hello world")


chaine = "Une instruction de code vraiment beaucoup trop longue" \
"pour être lisible si elle est écrite sur une seule et" \
"unique ligne !"
print ( chaine )

n° 26

13
Les blocs
 En algorithmie, les blocs servent à délimiter une séquence d’instructions.
 L’objectif étant d’exprimer un périmètre de validité à ces instructions.
 En Python, l’usage du « : » permet de démarrer un bloc, ensuite, il est
nécessaire d’utiliser une tabulation supplémentaire par rapport au niveau de
tabulation courant, pour exprimer le contenu du bloc.
 Les tabulations ne sont donc pas cosmétiques en Python !
 Exemple :

def simple_methode(valeur):
if valeur < 0 :
res = "negatif"

n° 27

Structure d’un programme


 La réalisation d’un script python peut se réaliser de plusieurs façons :
 Ecriture depuis la console Python qui est un outil interactif permettant
d’exécuter à la volée des instructions de code

 Ecriture dans un fichier qui a une extension *.py.

print ("hello world")

n° 28

14
Structure d’un programme
 Python ne propose pas de point d’entrée d’application :
 Pas de main comme dans certains langages
 L’ensemble des instructions est exécutée
 Aucune fonction n’est appelée automatiquement.
 Ce manque de structure fait partie intégrante de la philosophie mais peut être
perturbant dans des projets pour la relecture de code.
 Il est donc possible de définir un point d’entrée :

if __name__ == '__main__':
print ("hello world")
print (repr (__name__))

 Un module __name__est défini égal à '__main__ ’ lorsqu'il est lu à partir d'une


entrée standard, d'un script ou d'une invite interactive.
 __name__est stocké dans l'espace de noms global du module

n° 29

Les types de données simples


 Les types de données simples
 Entiers (int)
 Réels (float)
 Chaines de caractères (str )
o Entre " ou ‘
 Booléens (bool)
o Mots clés True et False

if __name__ == '__main__':
un_entier = 12
print (type (un_entier))
un_reel = 3.1415
print(type(un_reel))
un_booleen = True
print(type(un_booleen))
une_chaine = "hello world"
print ( type (une_chaine))

n° 30

15
Typage dynamique
 Typage dynamique
 Le typage d’une variable est réalisé lors de son affectation.
 Le type peut changer au cours du déroulement du programme

un_entier = 12
print ("valeur de un entier ",un_entier,"type : " , type ( un_entier))

un_entier = "121"
print("valeur de un entier ", un_entier, " type : ", type(un_entier))

n° 31

Typage dynamique fort


 Typage fort
 Pas de conversion implicite par commodité !
 Un entier reste un entier

un_entier = "121"
print("valeur de un entier ", un_entier, " type : ", type(un_entier))
resultat = un_entier + 3

n° 32

16
Les fonctions de conversion
 Chaque type de données simple possède une fonction de conversion
permettant de convertir une données vers ce type.
 str(), int(), float()

un_entier = "121"
print("valeur de un entier ", un_entier, " type : ", type(un_entier))
resultat = int( un_entier) + 3
print("resultat : " , resultat )

n° 33

Littéraux numériques
 But :
 Augmenter la lisibilité de certains nombres
 Se rapprocher de leur présentation dans la vie courante
 Moyens :
 Inclusion du caractère « _ »
 Autant de fois que nécessaire
 Exemple

milleMilliards= 1_000_000_000_000

n° 34

17
Les constantes
 Python ne permet pas de déclarer des constantes ( pas de mot clé ).
 La réalisation de constante est basé sur des conventions :
 Déclaration globale
 Identifiant représenté en lettres majuscules
 C’est un moyen d’avertir le programmeur que cette donnée ne doit pas être
modifiée :

PI = 3.14159

n° 35

Les opérateurs
 Un opérateur est un caractère ou une suite de caractères à laquelle la
grammaire de Python donne une signification particulière.
 Les opérateurs Python sont regroupés dans les familles suivantes :
 Opérateurs arithmétiques
 Opérateurs logiques
 Opérateurs d'assignation
 Opérateurs de comparaison
 Opérateurs d'identité
 Opérateurs d'inclusion

n° 36

18
Opérateurs : Arithmétiques & Logiques
 Opérateurs arithmétiques
 Les opérateurs arithmétiques sont utilisés avec des valeurs numériques pour
effectuer des opérations mathématiques courantes :
Opérateur Nom Exemple

+ Addition x+y

- Soustraction x–y

* Multiplication x*y

/ Division x/y

% Modulo x%y

** Exponentiel x ** y

// partie entière de la division x // y

 Opérateurs logiques
 Les opérateurs logiques sont utilisés pour combiner les instructions
conditionnelles :
Opérateur Description Exemple

and Retourne Vrai si les deux énoncés sont vrais x < 5 and x < 10

or Retourne Vrai si l'un des énoncés est vrai x < 5 or x < 4

not Inverse le résultat, retourne Faux si le résultat est vrai not(x < 5 and x < 10)

n° 37

Opérateurs : Assignation
 Les opérateurs d'assignation sont utilisés pour assigner des valeurs aux
variables :
Opérateur Exemple Equivaut à
= x=5 x=5
+= x += 3 x=x+3
-= x -= 3 x=x-3
*= x *= 3 x=x*3
/= x /= 3 x=x/3
%= x %= 3 x=x%3
//= x //= 3 x = x // 3
**= x **= 3 x = x ** 3
&= x &= 3 x=x&3
|= x |= 3 x=x|3
^= x ^= 3 x=x^3
>>= x >>= 3 x = x >> 3
<<= x <<= 3 x = x << 3

n° 38

19
Opérateurs : Comparaison & Identité
 Opérateurs de comparaison Python
 Les opérateurs de comparaison sont utilisés pour comparer deux valeurs :
Opérateur Nom Exemple

== Égal x == y

!= Différent x != y

> Supérieur à x>y

< Inférieur à x<y

>= Supérieur ou égal à x >= y

<= Inférieur ou égal à x <= y

 Opérateurs d'identité
 Les opérateurs d'identité sont utilisés pour comparer les objets, non pas s'ils
sont égaux, mais s'ils sont le même objet, avec le même emplacement
mémoire :
Opérateur Description Exemple

is Retourne Vrai si les deux variables sont le même objet x is y

is not Retourne Vrai si les deux variables ne sont pas le même objet x is not y

n° 39

Opérateurs : Inclusion
 Opérateurs d'inclusion
 Les opérateurs d’inclusion sont utilisés pour tester si une séquence est
présente dans un objet.
o Un élément dans une liste, un mot dans une chaine, …

Opérateur Description Exemple


in Retourne Vrai si une séquence avec la valeur spécifiée est x in y
présente dans l'objet
not in Retourne Vrai si une séquence avec la valeur spécifiée n'est x not in y
pas présente dans l'objet

n° 40

20
Les chaines de caractères
 Les chaines de caractères, comme tous les types de données, sont des objets.
A ce titre, une chaine de caractères possède un certain nombre de méthodes
internes permettant leur manipulation.
 Les chaines de caractères s’écrivent entre guillemets ou apostrophe.

message = "My name is Bond"


langage ='Mon langage favori Python'
print ( message )
print ( langage )

n° 41

Manipulation des chaines de caractères


 Le langage fournit un ensemble de fonctions permettant de manipuler les
chaîne de caractères :
 Longueur d’une chaine
 len(chaine)
 Gestion de la casse
 chaine.lower()
 chaine.upper()
 Appartenance
 mot in chaine
 Remplacement
 chaine.replace("a", "A")
 Découpage
 chaine.split()

n° 42

21
La classe Str
 La classe Str est immuable :
 Une chaîne de caractères ne peut pas être modifiée

message = "langage Python"


messageMaj = message.upper()
print (f"{message} {messageMaj}")
print ( message.find ( "Python"))
print ( "Python" in message )
print (message.split())
print ('join')
print("-".join(["James" , "Bond"]))

n° 43

Formatage des chaines de caractères


 Le formatage des chaines de caractères se fait en utilisant l’opérateur modulo
(%). Voici quelques possibilités :

langage = 'Python'
duree = 4
print("Bienvenue à la formation %s de %d jours" % (langage , duree) )

 Python pousse à l’usage d’une autre approche, utilisant la méthode format()


des chaines de caractères :

langage = 'Python'
duree = 5
print("Bienvenue à la formation {0} de {1} jours".format(langage, duree) )
print("Bienvenue à la formation {langage} de {duree} jours" \
.format(langage=langage, duree=duree))

n° 44

22
Formatage des chaines de caractères (3.6)
 Python propose un nouveau mécanisme pour le formatage de chaîne de
caractères : les f-string.
f"{valeur:formatage}"
 Il est possible de spécifier des options de formatage avancées directement à
l'intérieur des accolades. cf. https://realpython.com/python-f-strings/

langage = 'Python'
duree = 4
print(f"Bienvenue à la formation {langage} de {duree} jours")
print(f"Bienvenue à la formation {langage} de {duree*6} heures")

n° 45

Les chaines de caractères


 La gestion des chaîne de caractères a évolué entre Python et python 3:
 en 2.7, les chaînes sont par défaut des arrays d’octets, et il faut les décoder
pour obtenir de l’unicode.
 en 3, les chaînes sont par défaut de type ‘unicode’, et il faut les encoder pour
obtenir de un array d’octets.
 La version 3 prend plusieurs mesures pour éviter les bugs
 L’encodage par défaut du code est UTF8.
 L’encodage par défaut de lecture et d’écriture est UTF8.
 On ne peut plus mélanger ‘bytes’ et ‘unicode’.

n° 46

23
Gestion des chaînes de caractères
 La création d’un tableau d’octet demande de préfixer une chaîne avec ‘b’ :

langage = b"Bienvenue en Python"


print ( langage, type(langage))
str = langage.decode ( "utf8")
print ( str , type(str))

n° 47

Autres types de données


 Les types évolués
 Listes (list) liste = ["un", "deux", "trois"]
print("type", type(liste))
o Mutables ensemble = ("un" , "deux" , "trois")
 Liste non modifiable (tuple) print ( "type" , type (ensemble))
o Immutables ! dico = {"un":1, "deux":2, "trois":3}
print("type", type(dico))
 Dictionnaires (dict)
o Tableaux associatifs

 Le type spécial
 None
 Par exemple un retour nul de fonction

n° 48

24
Les listes (list) : création & déclaration
 La classe list fournit un ensemble de méthodes :
 Les listes sont modifiables. Il est possible d’ajouter, de modifier, de supprimer
un élément ou bien d’étendre la liste avec une autre.

liste = ["un", "deux", "trois" , "quatre"]


liste.append("cinq")
print (liste)
liste[2] = "DEUX"
liste.remove ("quatre")
for elem in liste:
print (elem)

n° 49

Le type énuméré (Python 3.4)


 Permet de restreindre les valeurs d'une variable
from enum import Enum

class Carte(Enum):
Pique = 1
Coeur = 2
Carreau = 3
Treffle = 4

 La classe Carte est une énumération (ou un enum).


 Les attributs Carte.Pique,Carte.Coeur, sont des membres de l'énumération et
sont fonctionnellement des constantes.
 Les membres de l'enum ont chacun un nom et une valeur:
 le nom de Carte.Pique est Pique,
 la valeur de Carte.Coeur est 2

n° 50

25
Manipulation d’un type énuméré
 Exemple :

carte = Carte.Coeur
print ( carte , carte.name , carte.value)
print ( type (carte))
for c in Carte:
print (c.name)

 Il est possible d’accéder dynamiquement au champ d’un enum ;

print ( Carte(2))
print ( Carte["Coeur"])

n° 51

Entrée et sortie standards


 Les notions d’entrée et de sorties d’un système d’exploitation sont
historiquement liées aux systèmes Unix et à la ligne de commande.
 On considère que pour interagir avec une commande en utilisant un
terminal, on utilisera :
 L’entrée standard (STDIN)
o Associée au clavier, elle permet à l’utilisateur d’envoyer des données à la commande.
 La sortie standard (STDOUT)
o Associée à l’écran, elle offre le résultat nominal de l’exécution de la commande.
 La sortie d’erreur (STDERR)
o Associée également à l’écran, elle permet l’affiche des problématiques rencontrées
lors de l’exécution de la commande.

Entrée standard Sortie standard


(Données au clavier) (Affichage du résultat)
Commande
Sortie d’erreur
(Affichage des erreurs)

n° 52

26
Sortie standard & sortie d’erreur
 Pour envoyer des données à l’écran en utilisant ces deux sorties, on utilise la
fonction print()de Python.
 print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
 Cette fonction prend un nombre valeurs variable en premier paramètre
(étoilé), les autres paramètres doivent donc être nommés.
 Note : Ces notions sont évoquées dans le module concernant les fonctions.
 L’affichage se fait par défaut sur la sortie standard (file=sys.stdout).

langage = 'Python'
duree = 4
print("Bienvenue à la formation",langage ,"de :", duree , "jours")

 Chaque valeur est séparé par le caractère exprimé par le paramètre sep
(l’espace par défaut).
 Un saut de ligne est appliqué par défaut à la fin de l’affichage, comme
indiqué dans la signature par le paramètre end.

n° 53

Sortie Formatées
 Les chaînes de caractères formatées ( f-strings) permettent d’inclure
directement la valeur d’expressions Python dans des chaines de caractères en
les préfixant avec f ou F
 L’expression à présenter devra être spécifiée entre {}
 L'expression peut être suivie d'un spécificateur de format

langage = 'Python'
duree = 5
print(f"Bienvenue à la formation {langage} de {duree} jours")
print(f"Bienvenue à la formation {langage:10} de {duree:4} jours")

n° 54

27
Entrée standard en Python
 La gestion de l’entrée standard en Python permet la saisie d’informations au
clavier lors de l’exécution d’un programme.
 La fonction input(), intégrée au langage (builtin), permet cela.

langage = input ("entrer votre langage préféré: ")


print ( langage)
duree = input ("entrer la durée de la formation: ")
print ( duree)

 Il est important de noter que :


 Le paramètre de la fonction input() est le « prompt » (message utilisateur) à
afficher.
 Le retour de la fonction est systématiquement une chaine de caractères.
o A convertir donc, éventuellement.

n° 55

Le cas de la sortie d’erreur


 Pour envoyer des données sur la sortie d’erreur, il faut simplement modifier
la valeur du paramètre file de la fonction print() !

Import sys
print ("ceci est un message d'erreur" , file=sys.stderr)

 NOTE : L’affichage en rouge est provoqué par la console intégré d’un IDE, en
l’occurrence ici : PyCharm. Le changement de couleur n’est pas géré
nativement par Visual Studio Code.

n° 56

28
Les structures de contrôle
 Les structures de contrôle permettent d’intervenir sur le déroulement d’une
séquence d’instructions.
 L’exécution, habituellement séquentielle, pourra donc se trouver modifiée.
 Il existe essentiellement 2 types de structures de contrôle :
 Les structures conditionnelles
o Elle permettent de conditionner l’exécution d’une série d’instruction
 Les structures itératives
o Plus communément appelées « boucles », elles permettent d’itérer sur un ensemble
de valeurs, ou pour un certain nombre de fois.

n° 57

La structure conditionnelle
 Dans le langage Python, la structure conditionnelle s’articule autour des mots
clés if, elifet else.
 if permet de définir une condition pour laquelle, les instructions du bloc
suivant seront exécutées. elifpermet de faire une ou plusieurs conditions
alternatives, et enfin else, est utilisé si aucune de ces conditions n’est
vérifiée.

Condition simple vérifiée Condition simple non vérifiée

valeur = 5 valeur = 5
if valeur > 3 : if valeur < 3 :
valeur += 1 valeur += 1
print ( valeur) print ( valeur)

n° 58

29
La structure conditionnelle :
Conditions élaborées

Condition et son contraire Condition et alternative

if valeur > 0 : if valeur > 0:


print ( "nombre positif") print("nombre positif")
else : elif valeur < 0:
print ( "nombre négatif") print("nombre négatif")
else :
print ( "valeur à zéro")

n° 59

La structure conditionnelle :
Expression

de la condition
Python permet une expression très « mathématique » de la condition. Là ou,
classiquement on écrirait par habitude :
if valeur >= 0 and valeur <= 20 :
valeur += 1
print ( valeur)

 Python permet la syntaxe suivante, plus claire et lisible :

if 0 <= valeur <= 20 :


valeur += 1
print(valeur)

n° 60

30
Les structures itératives
 Il existe deux structures itératives en Python :
 while
o On itère tant qu’une condition est vérifiée
 for
o On parcourt un ensemble d’éléments ou de valeurs

 Contrairement à d’autres langages, pas de structures de type until ou bien


do ... while

n° 61

La structure itérative while


 En anglais, while signifie « Tant que ».
 Le principe est donc d’écrire une condition, qui, tant qu’elle est vérifiée,
permettra d’itérer.

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

 Attention de bien prendre soin à faire évoluer l’expression de la condition !


 Sinon -> Boucle infinie !

n° 62

31
La structure itérative for
 La boucle for permet de faire des itérations sur un élément.
 Une chaine de caractères, un ensemble, une liste, un dictionnaire, …

langage = "Python" liste = ["un", "deux", "trois" , "quatre"]


for lettre in langage: for elem in liste:
print ( langage ) print (elem)

n° 63

Gestion d’intervalle (range)


 La fonction range() permet de générer des suites arithmétiques :
range ( start , stop , step )

for elem in range (5):


print ( elem)

for elem in range ( 2 , 6 , 2):


print ( elem)

n° 64

32
Les ruptures de séquence
 Dans certaines situations, il peut être pertinent d’interrompre complètement
une boucle ou bien l’itération en cours.
 Python dispose des mots clés break et continue pour cela.

Interruption de boucle

liste = ["un", "deux", "trois" , "quatre"]


for elem in liste:
if elem == "trois" :
break
print (elem)
Reprise de boucle

for elem in liste:


if elem == "trois" :
continue
print (elem)

n° 65

Module 4
Les fonctions

n° 66

33
Utilité des fonctions
 En programmation, les fonctions permettent de factoriser un ensemble
d’instructions.
 L’objectif étant la réutilisation !
 Cette séquence d’instruction est le plus souvent configurable par des
paramètres d’entrées.
 La fonction peut produire ou non un résultat final qui sera collecté par le
code qui appelle la fonction.

Entrée Sortie
(Paramètres) (Résultat)
Fonction

n° 67

Déclaration d’une fonction


 La déclaration d’une fonction est constituée des éléments suivants :
 Le mot clé def
 L’identificateur de la fonction (son nom !)
 Une paire de parenthèses avec éventuellement des paramètres sous forme de
variables.
 Ceci constitue la signature de la fonction.
 Un bloc est ensuite créé pour l’implémentation de la fonction (son code
interne)

def rechercher_minimum ( valeur1 , valeur2):


res = 0 Identificateur Paramètres
if valeur1 <= valeur2 :
res = valeur1
else:
res = valeur2
return res

n° 68

34
Utilisation d’une fonction
 Pour utiliser une fonction, il suffit de l’appeler par son identificateur tout en
spécifiant des valeurs pour les paramètres.
 Le résultat produit en sortie peut être associé à une variable, ou exploité par
une autre fonction, …

resultat = rechercher_minimum ( 2 , 5 )

 La portée d’une fonction est le module (fichier Python) qui la contient.


 Donc si une fonction est contenue dans un module différent de celui ou elle
utilisée, le module de la fonction doit être importé ! (Notion vue plus loin)

n° 69

Les paramètres
 Lorsqu’une fonction déclare des paramètres dans sa signature, il doivent
recevoir des valeurs au moment de l’appelle de la fonction
resultat = rechercher_minimum ( 2 , 5 )

def rechercher_minimum ( valeur1 , valeur2):


res = 0
if valeur1 <= valeur2 :
res = valeur1
else:
res = valeur2
return res

 Les paramètres se comportent comme des variables locales à la fonction.


 Ces variables ne sont visibles et utilisables qu’à l’intérieur du corps (le bloc) de
la fonction.

n° 70

35
Le retour d’une fonction
 Le retour d’une fonction est le résultat qu’elle produit à la fin de l’exécution
de son code d’implémentation.
 Certaines fonctions n’ont pas de retour.
 Ce retour met fin à l’exécution de la fonction.
 Les instructions situées après cette instruction de retour ne seront donc pas
exécutées !
 Le retour de la fonction est introduit par le mot clé return.
def rechercher_minimum ( valeur1 , valeur2):
res = 0
if valeur1 <= valeur2 :
res = valeur1
else:
res = valeur2
return res

n° 71

Les annotations
 Les annotations sont une nouveauté Python qui vont permettre d’ajouter des
métadonnées aux fonctions :
 spécifier le type des paramètres attendus,
 spécifier le type de la valeur de retour

def rechercher_minimum ( val1 : int, val2 : int ) -> int :


if val1 < val2 :
res = val1
else:
res = val2
return res

n° 72

36
Les annotations
 Elles ne sont pas destinées à vérifier au runtime le type des paramètres :
 Améliore la lisibilité du code
 Utiliser par les outils et pour la documentation

def test_annotation ():


resultat = rechercher_minimum ( 3 , 5 )
print ( resultat)
resultat2 = rechercher_minimum( "3" , "5")
print ( resultat2)
resultat3 = rechercher_minimum("3", 5)
print(resultat3)

n° 73

Les paramètres optionnels


 En Python, il est possible de définir des fonctions possédant des paramètres
optionnels.
 Il n’est donc pas obligatoire de leur attribuer de valeurs au moment de l’appel
de la fonction.
 Le principe consiste à attribuer une valeur par défaut à ces paramètres. Si
une valeur est donnée au moment de l’appel, alors elle est utilisée, sinon,
c’est la valeur par défaut.
 ATTENTION : les paramètres optionnels doivent se situer en fin de signature !
def ma_fonction ( param1 : int , param2 : int = 0 , param3 : int = 1):
resultat = param1 + param2 + param3
return resultat

somme = ma_fonction ( 10 , 20 , 30 )
somme = ma_fonction (10)
somme = ma_fonction ( 10 , 20)
#somme = ma_fonction () #erreur

n° 74

37
Les paramètres en nombre variable
 Dans la signature d’une fonction, il est possible d’exprimer que celle-ci peut
recevoir un nombre variable de paramètres.
 Le packing et l'unpacking sont deux concepts Python complémentaires qui
offrent la possibilité de transformer une succession d'arguments, nommés ou
non, en liste/tuple ou dictionnaire et vice-versa.
 Un seul paramètre est alors exprimé.
 Son nom est préfixé d’une *.
 Le paramètre est alors exploitable sous forme d’une liste.

def calcul_moyenne ( *valeurs):


return sum(valeurs) / len (valeurs)

moyenne = calcul_moyenne ( 2 , 4 , 6 , 8 , 10 )

n° 75

Les paramètres nommés


 Certaines fonctions, notamment des fonctions intégrées au langage, utilisent
des paramètres en nombre variable et des paramètres optionnels à la suite.
 C’est le cas par exemple de la fonction print() dont voici la signature
(extrait de la documentation officielle de Python) :
 print(*objects, sep=' ', end='\n',file=sys.stdout,flush=False)
 Cette fonction prend en effet en paramètre autant de valeurs que nécessaire
à afficher (*objects), ces valeurs sont séparées par un espace ( sep ) et
chaque ligne est terminée par un saut de ligne ( end ).
print ("un" , "deux" , "trois")
 Dans ce cas, comment exprimer une valeur pour end ou pour sep ???
 La solution consiste à nommer les paramètres au moment de l’appel de la
fonction !
print ("un" , "deux", "trois" , sep="#" , end=" fin")

n° 76

38
Les paramètres nommés en nombre variable
 Il est possible de spécifier un nombre de paramètres variable qui sont
nommés
 Un seul paramètre est alors exprimé.
 Son nom est préfixé de deux **.
 Le paramètre est alors exploitable sous forme d’un dictionnaire.

def calcul_moyenneV2 ( **valeurs):


resultat = 1
for key, value in valeurs.items():
resultat *= value
return resultat

moyenne = calcul_moyenneV2( val1=2, val2=4, val3=6)

n° 77

Valeur de retour multiple


 Un problème très fréquemment rencontré est l’absence de mécanisme pour
renvoyer plusieurs valeurs depuis une fonction.
 Il y a bien sûr des solutions de contournement, mais elles sont généralement
peu pratiques :
 Utiliser un tableau ou une liste ;
 Utiliser la classe Tuple ;
 Créer une classe spécifique pour représenter les résultats de la fonction.

n° 78

39
Valeur de retour multiple
 Il est possible de renvoyer plusieurs valeurs dans une fonction. Le langage
stocke les différentes valeurs dans une variable de type Tuple

def calcul_somme ( values):


nbr_valeur = 0
somme = 0.0
for val in values:
nbr_valeur += 1
somme += val
return nbr_valeur , somme

nbr , somme = calcul_somme ( range ( 5))


print ( nbr , " " , somme )

resultat = calcul_somme ( range ( 5))


print ( resultat[0] , resultat[1])

n° 79

L’instruction pass
 L’instruction pass est une instruction qui ne fait rien :
 Elle peut être utilisée lorsqu’une instruction est nécessaire pour fournir une
syntaxe correcte, mais qu’aucune action ne doit être effectuée.
 Elle permet donc de définir la structure de vos programme sans
l’implémentation final et sans générer d’erreur.

def foo ():


pass

 Cette instruction est applicable à tout type de bloc :

if val == 0:
pass

n° 80

40
Module 5
Les modules et les packages

n° 81

Utilité de la structuration en module


 Les applications complexes doivent faire preuve d’un découpage structurel
en divers fichiers pour :
 Améliorer la lisibilité
 Favoriser l’évolution des fonctionnalités
 Faciliter le travail en équipe
 Réutiliser facilement des fonctionnalités entre plusieurs applications
 Livrer et re-livrer simplement quelques parties d’applications
 En Python, les modules sont ces unités de structuration.

n° 82

41
Conception de modules
 Un module peut contenir:
 des fonctions,
 des instructions exécutables,
 des déclarations de variables
 Ces instructions sont destinées à initialiser le module. On les exécute
seulement la première fois que le module est importé quelque part.

#module mmath
print ( "*** Chargement du module math ***")

def rechercher_minimum ( valeur1: int , valeur2 : int ) -> int :


res = 0
if valeur1 <= valeur2 :
res = valeur1
else:
res = valeur2
return res

n° 83

Importation d’un module


 Lorsque des fonctionnalités présentes dans des modules doivent être
utilisées, il y a trois manières de les rendre disponibles et accessibles pour les
autres modules :
 Rendre visible un module
 Créer un alias sur le module
 Importer une ou plusieurs fonctionnalités

n° 84

42
Importation d’un module
 L’instruction import permet de rendre visible un module :
 L’instruction place le nom du module dans la table des symboles de
l'appelant. Les objets définis dans le module restent dans la table de symboles
privée du module.
 Pour accéder aux objets du module il faut donc les préfixer.

#module main
import mmath

if __name__ == '__main__':
res = mmath.rechercher_minimum ( 10 , 20 )

n° 85

Création d’un alias


 L’utilisation d’une fonctionnalité d’un module nécessite d’importer le module
à travers l’instruction « import »:
 L’instruction place le nom du module dans la table des symboles de
l'appelant. Les objets définis dans le module restent dans la table de symboles
privée du module .
 les objets du module ne sont accessibles que lorsqu'ils sont préfixés

import mmath as m
if __name__ == '__main__':
res = m.rechercher_minimum ( 10 , 20 )
print ( res )

n° 86

43
Importation de fonctionnalités de modules
 Il est également possible d’importer une ou plusieurs fonctionnalités d’un
module à l’aide de l’instruction from.
 La fonctionnalité se trouve donc directement disponible et visible dans le module
important la fonctionnalité.
 La syntaxe est plus concise.
 Attention cependant aux conflits sur les noms.
from mmath import rechercher_minimum

if __name__ == '__main__':
res = rechercher_minimum ( 10 , 20 )
print ( res )

 Le caractère * permet d’indiquer que l’on veut importer toutes les fonctionnalités
du module.
 Cette technique est déconseillée car elle ne permet pas d’avoir une vision claire des
fonctions qui ont été importées.

n° 87

Importation de fonctionnalités de modules


 Une fois importés, tous les modules possèdent cinq attributs qui contiennent
des informations :
 __all__ : contient toutes les variables, fonctions, classes du module
 __builtins__ : dictionnaire qui contient toutes les fonctions et classes
inhérentes au langage utilisées par le module
 __doc__ : contient l’aide associé au module
 __file__ : contient le nom du fichier qui définit le module
 __name__ : contient le nom du module sauf si le module est le point d’entrée
du programme auquel cas cette variable contient le main.

print (pmath.mmath.__name__)
print ( pmath.mmath.__file__)
print ( dir ( pmath))

 La commande dir donne une liste d’attributs valides pour le module spécifié.

n° 88

44
Organisation en packages
 Les modules peuvent se trouver stockés dans une arborescence de
packages:
 L’objectif est d’assurer l’unicité des noms des modules !
 Un package est un dossier, ni plus, ni moins.
 Il peut contenir un fichier spécial __init__.py qui permet à Python de
reconnaitre le répertoire comme package. Ce n’est plus obligatoire.
 Ce fichier est généralement vide

n° 89

Accès à un package
 les packages font partis du nom du module.
 L’accès aux fonctions se fera en mentionnant le nom complet.

import pmath.mmath
res = pmath.mmath.rechercher_minimum ( 10 , 20 )

from pmath.mmath import rechercher_minimum


res = rechercher_minimum ( 10 , 20 )

n° 90

45
Le fichier __init__
 Il permettait à Python de distinguer des répertoires des packages.
 Ce fichier est généralement vide
 Il permet de spécifier les fonctionnalités du package que l’on veut exporter

#fic
from pmath.mmath import rechercher_minimum

n° 91

Le module principal
 En Python, contrairement à d’autres langages, il n’y pas spécifiquement de
point d’entrée de programme.
 A l’instar du main()du C, du C++ ou du Java !
 Il est cependant courant de trouver une structure de module simulant cette
notion.
 Il s’agit de tester si le module est invoqué directement par l’ interpréteur
Python.
o Dans ce cas là, le module porte le nom spécial__main__

if __name__ == '__main__':
pass

n° 92

46
Le chemin de localisation des modules :
PYTHONPATH
 Le PYTHONPATH permet d’indiquer à Python quels dossiers il doit prendre
en compte pour sa recherche de modules.
 Il est visualisable de la manière suivante :

import sys
print ( sys.path)

 Le PYTHONPATH inclue toujours le répertoire courant depuis lequel les


commandes sont passées.
 Il inclut également la bibliothèque standard Python !

 Certains programmes nécessites l’ajout de répertoires supplémentaires au


PYTHONPATH.

n° 93

Ajouter un répertoire au PYTHONPATH


 Il existe deux techniques pour ajouter un répertoire au PYTHONPATH :
 Avec une variable d’environnement.
o De manière permanente sur le système d’exploitation, ou bien en la valorisant
temporairement via un script système ou avant d’exécuter un programme.
o UNIX
• export PYTHONPATH=$PYTHONPATH:<nouveau répertoire>:<…>
o WINDOWS
• set PYTHONPATH=%PYTHONPATH%;<nouveau répertoire>;<…>
 Dynamiquement dans un programme Python, par programmation.

import sys
print ( sys.path.insert ( 0 , "/home/scripts" ))

n° 94

47
Les modules Python
 Python fournit une bibliothèque standard qui contient un ensemble de
modules proposant des fonctions prédéfinies:
 math: traitement mathématique
 date: traitement de date
 re: expression régulière
 Il existe d’autres bibliothèques que l’on doit installer explicitement
 numpy : calcul scientifique. Elle introduit une gestion facilitée des tableaux.
 Pandas, matplotlib ...

n° 95

Module 6
POO : Les classes

n° 96

48
Les classes
 Une classe est une entité qui regroupe des attributs et des méthodes

class NomClasse :

#attributs
def __init__(self) :
self.__nomAttribut1 = valeurInitiale
self.__nomAttribut2 = valeurInitiale

#méthodes
def nom_fonction(self, paramètre1, paramètre2) :
# code de la fonction

n° 97

Attributs et méthodes
 Membres d'instance
 Les valeurs sont propres à chaque objet !
 Pas d'ordre dans les déclarations.
 Attributs
 Définit dans la méthode init avec le mot clé self
 Peut être un type simple ou complexe
 Méthodes
 L’équivalent d'une fonction ou d'une procédure dans un contexte objet
 Une référence à l’objet en cours est obligatoire !
o Le premier paramètre d’une méthode.
o Le plus souvent nommé « self »
o Permet l’accès aux membres

n° 98

49
Exemple
class Voiture : Voiture
immatriculation : str
def __init__(self ): kilométrage : float
self.__kilometrage = 0 carburant : float
self.__carburant = 20 consommation : float
self.__immatriculation = "ABC-ZE-44"
self.__consommation = 5 rouler(distance : float)

def rouler ( self , distance : int ):


self.__kilometrage = self.__kilometrage + distance
self.__carburant = (self.__carburant) – \
(distance * self.__consommation / 100 )

#méthode qui va convertir un objet en chaine


def __str__ ( self):
return f"{self.__immatriculation} {self.__kilometrage} " \
f"{self.__carburant} {self.__consommation} {self.__reservoir} "

n° 99

L’instanciation
 Une classe est un type à partir duquel on va créer des objets.
 La création d’un objet à partir d’une classe est appelée une instanciation. Elle
se réalise sous la forme suivante :
v = Voiture()
1 3 2

1. Création d'une « variable de manipulation d'une Voiture ». Pas de création de


Voiture. Valorisée à None
2. Création d'une nouvelle instance de Voiture. Cela se traduit par une
réservation de mémoire à une adresse (par ex: @100)
3. Affectation de la Voiture nouvellement créée à la variable v par recopie de
l'adresse

« v" n'est pas l'objet, mais un moyen de le manipuler

n° 100

50
Manipulation d’un objet
 Toute manipulation d’objet s’effectue par "envoi de message".
 L’envoi d’un message est composé de trois parties :
 une référence permettant de désigner l’objet récepteur,
 le nom de la méthode à exécuter,
 les paramètres éventuels de la méthode
 La mise en œuvre se réalise avec l'opérateur "."
 s'applique à la référence sur l'objet
 n'est possible que si la référence n'est pas nulle
 Envoi d'un message à un objet destinataire et en réponse, l'objet déclenche
un comportement
def test_voiture() :
v = Voiture()
v.rouler(20)
print ( v )

n° 101

Modification d’objet dynamique


 Le langage permet de modifier la structure d’un objet dynamiquement :

class Voiture :
def __init__(self ):
self.__kilometrage = 0
self.__carburant = 20
self.__immatriculation = "ABC-ZE-44"
self.__consommation = 5

def remplir_reservoir ( self ) :


self.__reservoir = 50 # ajout d’un attribut dans l’objet

def __str__ ( self):


return f"{self.__immatriculation} {self.__kilometrage} " \
f"{self.__qteCarburant} {self.__consommation} {self.__reservoir}"

n° 102

51
L’encapsulation
 L'objet doit se protéger
 Expression de la visibilité des membres
 Privés : invisible à l'extérieur de la classe, même en lecture
 Publiques : manipulable de l'extérieur de la classe, même en écriture
 Démarche : sauf bonne raison, on cache les données qui ne doivent être
accessible que par les méthodes.
 En Python
 Tout est considéré publique par défaut !
 La notion d’éléments privés peut être exprimée en préfixant les membres avec
__ (double underscore)

n° 103

Les accesseurs
 Un objet n’est manipulable que par les méthodes spécifiées dans sa classe.
 Toute tentative de manipulation de la partie privée entraîne une erreur.

def test_voiture() :
v = Voiture()
v.rouler(20)
print ( v.__carburant ) #erreur

 Pour accéder aux données il faut donc prévoir des méthodes : les accesseurs.
 Elles peuvent être en lecture ( "getters" ) et/ou en écriture ("setters") et
doivent contrôler l’intégrité des données.

 Les setters sont également appelés mutateurs car ils modifient l’attribut.

n° 104

52
Exemple

class Voiture :
def __init__(self ):
self.__kilometrage = 0
self.__qte_carburant = 20 def test_voiture() :
self.__immatriculation = "ABC-ZE-44" v = Voiture()
self.__consommation = 5 v.rouler(20)
print ( v.get_carburant())
def get_kilometrage(self): print(v.get_kilometrage())
return self.__kilometrage

def get_carburant(self):
return self.__qte_carburant

n° 105

Les accesseurs en écriture


 Elles permettent de modifier les états des objets et doivent toujours vérifier
la cohérence des données.
 Dans la classe « Vehicule » veut remplir le réservoir :
 Le véhicule à un réservoir d’une capacité de 50 litres.

def set_carburant(self, carburant : float ):


if carburant <= 50:
self.__carburant = carburant

n° 106

53
Initialisation des attributs d’une classe
 Il est souvent nécessaire d’initialiser les attributs pour donner un sens aux
objets.
 Dans ce cas il faut prévoir des paramètres dans la méthode __init__
def __init__(self, immatriculation : str , kilometrage : float ,
carburant : float , consommation : float ):
self.__immatriculation = immatriculation
self.__kilometrage = 0 # ou kilometrage
self.__qteCarburant = carburant
self.__consommation = consommation

 La méthode __init__ est appelé implicitement lors de la création


 La création d’objet doit donc respecter le mode de création imposé par la
classe en fournissant les valeurs attendues.
def test_voiture() :
v1 = Voiture("ABC-ZE-44" , 20000 , 10 , 0.7 )
print(v1)
n° 107

Utilisation des valeurs par défaut


 Il est possible de fournir des valeurs par défaut à la méthode __init__

def __init__(self, immatriculation, kilometrage,


qteCarburant = 0 , consommation = 5 ):
self.__immatriculation = immatriculation
self.__kilometrage = kilometrage
self.__qteCarburant = qteCarburant
self.__consommation = consommation

def test_voiture() :
v1 = Voiture("ABC-ZE-44" , 20000 , 10 , 0.7)
v2 = Voiture("DEF-YB-35", 500)
print(v1)
print(v2)

n° 108

54
Le garbage collector

 Une fois initialisé par la « PVM », le "garbage collector" alloue un segment de


mémoire pour stocker et gérer des objets.

 Cette mémoire est appelée tas managé, par opposition à un tas natif dans le
système d'exploitation.

 Tout objet est créé en spécifiant le nom de la classe à instancier

 Un objet conserve son emplacement mémoire tant qu’il est référencé.

n° 109

Le garbage collector
 La récupération de la mémoire (libération) est assurée par le garbage
collector (ramasse miettes).
 C’est un thread qui s’exécute au sein de la PVM et qui libère la mémoire
quand celle-ci n’est plus utilisée.
 Son fonctionnement est basé sur deux algorithmes
 Comptage de références
 Un algorithme de détection de cycle (références circulaires)
 Le passage du «garbage» est réalisé en fonction d'un seuil d'allocations
d'objets et de «désallocations» d'objets.
 Lorsque le nombre d'allocations moins le nombre de désallocations est
supérieur au nombre de seuil, le garbage collector est exécuté.

n° 110

55
Le garbage collector
 On peut inspecter le seuil à l’aide de la méthode get_treshold de la classe gc
print("Garbage collection thresholds:", gc.get_threshold())

 Le seuil par défaut sur le système est de 700.


 Cela signifie que lorsque le nombre d'allocations par rapport au nombre de
désallocations est supérieur à 700, le ramasse-miettes s'exécutera.
 Le GC classe les objets en trois générations en fonction du nombre de balayages
de collection auxquels ils ont survécu.
 Les nouveaux objets sont placés dans la plus jeune génération (génération 0).
 Si un objet survit à une collection, il est déplacé dans la prochaine génération plus
ancienne.
 la collecte démarre. Au départ, seule la génération 0 est examinée.

n° 111

Le garbage collector
 Il est possible d’invoquer explicitement le garbage collector à l’aide de la
méthode Collect :
Collect = gc.Collect()

 Attention, lorsque le garbage collector s’exécute, tous les threads en cours


d’exécution sont interrompus.
 La classe GC propose d’autres méthodes :
 gc.count() : permet d’indiquer au garbage collector, de ne pas exécuter le
destructeur lors de la destruction de l’objet.
 gc.stats() Renvoie une liste de trois dictionnaires par génération contenant des
statistiques de collection depuis le démarrage de l'interpréteur.
o collections est le nombre de fois où cette génération a été collectée;
o collected est le nombre total d'objets collectés au sein de cette génération;
o uncollectableest le nombre total d'objets qui se sont avérés irrécupérables (et ont
donc été déplacés vers la garbage liste) au sein de cette génération.

n° 112

56
Le destructeur
 Il est possible de prévoir un traitement avant la libération des objets : le
DESTRUCTEUR.

 Le destructeur est appelé par le garbage collector juste avant la destruction


effective.

 Un destructeur est représenté par la méthode __del__

n° 113

Suppression d’une référence


 Il est également possible de détruire un objet avant la sortie de sa porté avec
la méthode del :
 del obj

def test_voiture ():


v1 = Voiture("ABC-ZE-44", 20000, 10, 0.7 )
print (v1)
del v1
print ( v1 )

UnboundLocalError: local variable 'v1' referenced before assignment

 Attention la méthode del détruit uniquement la référence ( pas l’objet )

n° 114

57
Membres de classe
 Question : comment mettre en place un système de comptage de voitures ?
 Quel problème rencontre-t-on ?
Voiture
@100
immatriculation : String 1
kilométrage : double Autant de
qteCarburant : double 1 compteurs
consommation : double @110
que d'objets !
nbr_voitures : int
1
rouler(distance : double)
@120

class Voiture :

def __init__(self, immatriculation, kilometrage, qteCarburant, consommation):


self.__immatriculation = immatriculation
self.__kilometrage = kilometrage
self.__qteCarburant = qteCarburant
self.__consommation = consommation
self.__nbr_voitures += 1
n° 115

Membres de classe
 Parfois des données ne relèvent pas de l'instance mais de la classe
 Membre de classe ≠ membre d'instance
 Attributs de classe
 Méthodes de classe
 Les méthodes d'instance peuvent accéder aux membres de classe
 Les méthodes de classe ne peuvent pas accéder aux membres d'instance

n° 116

58
Membres de classe
 La déclaration d’une variable de classe se fait au sein de la classe (en dehors
de toute méthode).
 La manipulation d’une variable de classe se réalise à travers le nom de la
classe :
NomClasse.__attribut
 Il faudra prévoir des méthodes de classes pour y accéder :
 On utilise le décorateur @classmethod sur les méthodes pour indiquer
Que ce sont des méthodes de classe
 Un décorateur est une méta-données positionnée sur un élément de code.
 Les décorateurs sont toujours préfixés par le caractère @

n° 117

Membres de classe
Voiture
immatriculation : String
kilométrage : double
qteCarburant : double
class Voiture :
__nbr_voitures = 0 consommation : double
nbrVoitures : int
@classmethod rouler(distance : double)
def get_nbr_voitures(cls):
return cls.__nbr_voitures

def __init__(self, immatriculation, kilometrage, qteCarburant=0, consommation=0.5):


self.__immatriculation = immatriculation
self.__kilometrage = kilometrage
self.__qteCarburant = qteCarburant
self.__consommation = consommation
Voiture.__nbr_voitures += 1

n° 118

59
Membres de classe
 Accès
 Les membres sont accédés à partir du nom de la classe et non plus à partir du
nom de l’instance.

def test_voiture() :
v1 = Voiture("ABC-ZE-44" , 20000 , 10 , 0.7)
v2 = Voiture("DEF-YB-35", 500)
print(v1)
print(v2)
print(f" nombre de voiture : {Voiture.get_nbr_voitures()}")

n° 119

Les propriétés
 L’utilisation des accesseurs peut alourdir la lisibilité du code ce qui va à
l’encontre de l’esprit Python.
 Il est possible de masquer leurs utilisations à l’aide des décorateurs:
class Voiture :
def __init__(self ):
self.__carburant = 20
@property
def carburant(self):
return self.__carburant

def test_voiture() :
v = Voiture()
v.rouler(20)
print ( v.carburant )

n° 120

60
Les propriétés en écriture
 Il est possible d’utiliser les décorateurs pour définir des propriétés en
écriture:

@carburant.setter
def carburant(self, carburant):
if carburant > 0 and carburant <= 50:
self.__carburant = carburant

def test_voiture() :
v = Voiture()
v.carburant = 20
v.rouler(20)
print ( v)

n° 121

Module 7

POO : L’héritage

n° 122

61
Héritage et classe dérivée
 L’héritage permet de créer une classe, par extension, ou spécialisation d’une
classe existante.

 Chaque niveau (classe) amène un complément ou une spécialisation des


caractéristiques du niveau supérieur auquel il est rattaché.

 Dès lors qu'une caractéristique (attribut ou méthode) est définie à un niveau,


elle reste valable pour tous les sous-niveaux affiliés.

 Ce mécanisme est appelé l'héritage. Si une classe B hérite d'une classe A, la


classe B est appelée classe dérivée et A classe de base.

n° 123

Exemple

class Personne:

def __init__ ( self, nom , age ):


self.__nom = nom
self.__age = age

def get_nom ( self):


return self.__nom

def get_age(self):
return self.__age

def anniversaire (self):


self.__age = self.__age + 1

def __str__ (self):


return f"nom: {self.__nom} age: {self.__age}"

n° 124

62
Héritage
 On veut créer une classe Stagiaire.
 Un Stagiaire est une personne qui suit un cours.
 La mise en œuvre de l’héritage se réalise au moment de la conception de la
nouvelle classe en spécifiant la classe dont on veut hériter :

class Stagiaire(Personne):
pass

 La classe Stagiaire hérite de Personne.


 Elle possède donc les attributs et les méthodes de la classe Personne.

n° 125

La classe Stagiaire
 La classe Stagiaire complète la classe Personne en intégrant la notion de
cours :

class Stagiaire(Personne):

def __init__(self , cours ):


self.__cours = cours

def get_cours(self):
return self.__cours

def set_cours(self, cours):


self.__cours = cours

n° 126

63
Les constructeurs
 Un constructeur d’une classe dérivée doit toujours invoquer un constructeur
de la classe de base
 Contrairement à ce qui se passe dans certains langages orientés objet, la
délégation n’est pas implicite en Python. Il faut y procéder explicitement :
 Il existe deux possibilités pour appeler le constructeur de la classe de base:
 SuperClasse.__init__(self, ...) #Python2
 super().__init__(…) #Python3

def __init__(self , nom , age , cours ):


super().__init__( nom , age ) #Python 3
self.__cours = cours

Appel du constructeur
de la classe Personne

n° 127

Héritage
 La création d’un objet s’effectue à travers le nom de la classe

stag1 = Stagiaire ( "Dupont" , 40 , "Python")

 Un objet stagiaire peut solliciter les méthodes définies dans sa classe :

stag1.set_cours("Java")

 Un objet stagiaire peut solliciter les méthodes définies dans sa hiérarchie


(méthodes de la classe Personne) :

stag1.anniversaire()

Appel de la méthode "anniversaire" de la classe Personne.

n° 128

64
Redéfinition de méthode
 Que se passe-t-il lorsque l’on tente d’afficher un objet Stagiaire :

stag1 = Stagiaire ( "Dupont" , 40 , "Python")


print(stag1)

 C’est la méthode « str » de la classe Personne qui est appelée. Le cours n’est
donc pas affiché.
 On peut donc considérer que cette méthode ne remplit pas son rôle pour un
objet stagiaire :
 il faut donc la redéfinir.

n° 129

Redéfinition de méthode
 Lorsque l’on redéfinit une méthode, elle vient masquer celle du niveau
supérieur qui devient donc inaccessible.

def __str__(self):
return super().__str__() + f" Cours: {self.__cours}

n° 130

65
La classe dérivée "Stagiaire"
 Les caractéristiques héritées sont tributaires des attributs d'accès des champs
de la classe de base.

 Les champs publics de la classe "Personne" sont bien-sûr accessibles pour les
méthodes de la classe "Stagiaire" :

def __str__(self):
return super().__str__() + f" Cours: {self.__cours}

n° 131

La classe dérivée "Stagiaire"


 Les champs privés de la classe "Personne" sont inaccessibles pour les
méthodes de la classe "Stagiaire" :

def __str__(self):
return f" Nom:{ self.__nom } Cours: {self.__cours}"

erreur _nom est "private"

n° 132

66
L'attribut d'accès protected
 L’héritage ne doit pas être un moyen de contourner l’encapsulation.
 Les attributs privés d’une classe sont dont inaccessibles pour la classe dérivée.
 Python met à disposition un attribut d’accès qui permet de concéder un droit
d’accès à une classe dérivée : protected
 Basé sur des règle de nommage
 Doit commencer par un simple _
 Simple indication que cet attribut ne doit être accessible que depuis une
classe dérivée ( pas de contrôle)

class Personne :
def __init__ ( self, nom , age ):
self._nom = nom
self.__age = age

n° 133

La classe Object
 Toute classe hérite implicitement de la classe object
.
 L’ensemble des classes Python se présente donc sous la forme d’une
hiérarchie unique.
 En Python, la classe object est la super-classe de toutes les classes.
 class Personne : identique à class Personne ( object ) :
 Elle possède un ensemble de méthodes qui sont donc héritées par toutes les
classes Python.

N° 133 bis

67
Classes et méthodes abstraites
 Certaines classes ne doivent pas être instanciées
 Souvent car cela n’a pas de sens, par exemple un véhicule
 Elles doivent pour cela hériter de la classe ABC (Abstract Base Class)
 Nécessite d’importer la classe « ABC » du module « abc »

 De plus, ces classes contiennent des méthodes abstraites


 Qui ne possèdent pas de code et doivent être surchargées
 Elles doivent être marquées avec l’annotation @abstractmethod

from abc import ABC, abstractmethod


class Vehicule (ABC) :
@abstractmethod
def run ( self, nb_kilometres ):
pass

n° 134

67
La méthode str
 La méthode str permet une conversion de l’objet en chaîne de caractères.
 Elle renvoie par défaut le nom de la classe et l’adresse de l’objet

def test_personne():
p1 = Personne ("Dupont" , 40 )
print(p1) Appel de la méthode str
de Object

<__main__.Personne object at 0x000001E81DCE8400>

n° 135

La méthode str ()
 Les classes métiers doivent redéfinir la méthode str pour assurer l’affichage
des objets :

def test_personne():
p1 = Personne ("Dupont" , 40 )
print(p1) Appel de str
de la classe Personne

class Personne:

def __init__ ( self, nom , age ):


self.__nom = nom
self.__age = age

def __str__ (self):


return f"nom: {self.__nom} age: {self.__age}"

n° 136

68
Les méthodes spéciales des objets
 Les méthodes spéciales, héritées de object, permettent le bon
fonctionnement du modèle objet de Python.
 Parmi ces méthodes, __eq__, __ge__, __gt__, __le__, __lt__et __ne__
sont des comparateurs.

Opérateur Méthode
== __eq__
>= __ge__
> __gt__
<= __le__
< __lt__
!= __ne__

n° 137

Egalité entre objet


 L’opérateur == appelle la méthode __eq__

def test_personne():
p1 = Personne ("Dupont" , 40 )
p2 = Personne("Dupont", 40)

if p1 == p2:
print("egalite")
else:
print("different")

n° 138

69
Redéfinition des méthodes spéciales
 La redéfinition de ces méthodes spéciales au sein des classes permet aux
objets de ces classes de s’approprier spécifiquement les opérateurs de
comparaison.
def __eq__(self, other):
if ( isinstance( other , Personne)):
return self.__nom == other.__nom
else :
return -1

 Il n’y a pas de relations implicites entre les opérateurs de comparaison.


 La vérité de x==y n’implique pas que x!=y est faux.
 Par conséquent, lors de la définition de la méthode « eq », il faut également
définir la méthode « ne »
 La redéfinition de la méthode « eq » nécessite également la redéfinition de
la méthode « hash » pour pouvoir utiliser les collections correctement.

n° 139

La surcharge des opérateurs


 Sur le même modèle que précédemment, les opérateurs arithmétiques sont
également associés à des méthodes.
 Qui peuvent, elle aussi, être redéfinie dans les classes.

Opérateur Méthode Signification


+ __add__ Addition
- __sub__ Soustraction
* __mul__ Multiplication
/ __truediv__ Division
// __floordiv__ Division entière
% __mod__ Modulo
** __pow__ Puissance

n° 140

70
Le polymorphisme
 Le polymorphisme est la faculté pour un même message de prendre des
formes différentes :

Voler à 5000 pieds

n° 141

Compatibilité d’instance
 La classe Stagiaire peut être vue comme un "sous type" de la classe
Personne
 stag1 est une instance de la classe Stagiaire mais stag1 est aussi une
instance de la classe Personne.
 Il est donc possible de regrouper des objets d’une même hiérarchie dans une
collection.

tabPersonnes = []
tabPersonnes.append(Personne("Dupont", 40))
tabPersonnes.append(Stagiaire("Martin", 45, "Python"))
for p in tabPersonnes :
print (p.__str__() )

n° 142

71
Module 8
Gestion des exceptions

n° 143

x
Les exceptions
 Besoin de gérer les erreurs
def diviser ( valeur1 , valeur2 ):
res = valeur1 / valeur2 Problème possible !
return res

 Historiquement : code retour d'une fonction


 Détournement du fondement mathématique de la syntaxe

CODE_ERREUR = -1

def diviser ( valeur1 , valeur2 ):


if valeur2 != 0 :
res = valeur1 / valeur2
return res
else :
return CODE_ERREUR

n° 144

72
Les exceptions (suite)
 Besoin d'un autre canal de sortie : les erreurs
 Séparation du flux de données et d'erreurs
 La syntaxe d'appel redevient naturelle
 Syntaxe appropriée en cas d'erreur
 En Python, les erreurs sont des objets :
 ClasseException
 Il faut les créer
 2 parties
 La détection du cas d'erreur = émission de l'erreur
 Le traitement de l'erreur

n° 145

Les exceptions : différents types


 La bibliothèque standard Python contient un certain
nombre de classes d’exception prédéfinies.
 Elle peuvent être utilisées si leur nom est
suffisamment représentatif du type d’erreur à exprimer
!
 Elles peuvent également servir de super-classe pour
des exceptions utilisateur.
 Dans ce cas, il est préconisé d’hériter de Exception
où de l’une de ses sous-classes.

Schéma tiré de la documentation officielle de Python


https://docs.python.org/3/library/exceptions.html#exception-hierarchy

n° 146

73
Les exceptions : origine de l'erreur
 La mise en œuvre (levée) des exceptions s’effectue avec le mot clé raise :

def diviser ( valeur1 , valeur2 ):


if valeur2 != 0 :
res = valeur1 / valeur2
return res
else :
raise Exception ( "division par zéro impossible ")

 La définition du déclenchement d’exception laisse « sortir » l’objet d’erreur


par un autre canal de sortie.

Entrée (paramètres…) Sortie standard (return…)


Fonction / Méthode

Sortie d’erreur (raise…)

n° 147

Les exceptions : traitement de l'erreur


 Gérer les exceptions est presque obligatoire
 Toute exception non gérée correctement conduira à la fin de l’exécution de
l’interpréteur Python !

res = diviser ( 5 , 0 ) #ZeroDivisionError: division by zero

 La gestion des exceptions se réalise à l’aide de l’instruction


try: ... except: ...

def test_exception () :
try:
res = diviser ( 5 , 0 )
except Exception as e:
print (e)

n° 148

74
La structure try : … except : …
 L’idée consiste à écrire les instructions de code critique, celles qui peuvent
déclencher une exception, dans un bloc try.
 En cas de déclenchement d’exception, le code situé dans le bloc except
sera exécuté.

Exécution normale
try:
Exécution avec exception # Instructions de code critique

… Exception déclenchée

except:
# Code de gestion de l’erreur

# Suite du code

n° 149

Les exceptions utilisateur


 Avoir ses propres classes d'exceptions
 Exceptions techniques
 Exceptions métiers
 Exceptions de présentation
 Hériter de Exception
 Ajouter des attributs et des méthodes
o ex : code d'erreur
 Reprendre éventuellement le constructeur

n° 150

75
Exemple

class SosException ( Exception) :


def __init__ ( self , message = "Bateau en détresse") :
super().__init__(message)

class Voilier:
def manoeuvre(self) :
probleme = True
if probleme :
raise SosException ( "Erreur de manoeuvre ")

n° 151

Exemple

def test_exception () :
v = Voilier()
try :
v.manoeuvre()
print ( "manoeuvre effectuée, on continue")
except SosException as e :
print ( e )
print ("on continue la croisière")

n° 152

76
Gestion de plusieurs erreurs
 Il est possible de faire suivre le bloc try de plusieurs blocs except.
 Ils permettront de faire un traitement approprié en fonction du type
d’exception déclenché.
 Chaque bloc exceptdoit alors mentionner le type d’exception qu’il prend en
charge.
 Un dernier bloc except« générique » permettra la gestion des erreurs non-
prévues.

try:

except NameError as e:

except TypeError as e:

except:

n° 153

Les exceptions : finally


 Parfois, il faut avoir la garantie d'exécuter du code même en cas d'exception
 Exemple : libération de ressources (connexion, référence de fichier, …)
 Le bloc finally

ressource = UneRessource()
try:
ressource.traiter()
except ExceptionTechnique as e:
raise ExceptionFonctionnelle("message fonctionnel")
finally:
ressource.close()

n° 154

77
Module 9

Les collections : aspects avancés

n° 155

Les collections
 Le langage propose plusieurs types de collections :
 Les listes: collection de valeurs associées à un indice numérique ordonné à
partir de zéro.
 Les Tuples : collection non modifiable de valeurs associées à un indice
numérique ordonné à partir de zéro.
 Les dictionnaires : collection de valeurs associées à une clé, on maitrise le type
de la clé.
 Les ensembles ( Set) : collection qui gère l’unicité des éléments qui ne sont
pas placé dans un ordre particulier.

n° 156

78
Les Listes
 Une liste est un ensemble d’éléments de même type ou non.
La mise en œuvre se réalise à l’aide de l’opérateur [].

__liste_personnes = []

__liste_personnes.append ( Personne ( "nom1" , 30))


__liste_personnes.append ( Personne ( "nom2" , 50))
__liste_personnes.append ( Personne ( "nom3" , 40))

 La méthode append permet d’ajouter des éléments.

n° 157

Parcours d’une liste


 Le parcours d’éléments se réalise en fonction du nombre d’éléments dans la
liste:

def get_personnesV1(self):
result = 'Liste des personnes : \n'
nbr = 0
while nbr < self.__liste_personnes.__len__() :
result += self.__liste_personnes[nbr].__str__() + "\n"
nbr += 1
return result

 Il peut être intéressant d’avoir une technique de parcours homogène


indépendante du type de la collection :
 Les itérateurs

n° 158

79
Les itérateurs
 Un littérateur est un objet permettant de parcourir tout autre objet dit
« itérable » :
 C’est une sorte de curseur qui a pour mission de se déplacer dans une
séquence d'objets.
 Il permet de parcourir chaque objet d'une séquence sans se préoccuper de la
structure sous-jacente.
 Les principaux objets itérables sont :
 Les collections
 Les chaîne de caractères
 Les fichiers

n° 159

Les itérateurs
 Python possède une fonction faisant partie des Built-In (fonctions de base)
nommée « iter() ».
 Cette fonction permet de créer un itérateur sur un objet itérable.
 Un itérateur Python doit posséder une méthode __next__ qui ne prend pas
d'argument et renvoie toujours l'élément suivant du flux. S'il n'y plus
d'élément dans le flux, la méthode doit lever une exception de type
StopIteration.

def get_personnesV2(self):
result = 'Liste des personnes : \n'
iterateur = iter ( self.__liste_personnes)
while True:
try:
result += next(iterateur).__str__() + "\n"
except StopIteration as stop:
break
return result

n° 160

80
Les itérateurs
 Python fournit une structure itérative qui s’attend à travailler avec des
itérateurs et qui va nous simplifier (grandement) la syntaxe :
 La structure for

def get_personnesV4(self):
result = 'Liste des personnes : \n'
for val in IterPersonnes ( self.__liste_personnes):
result += val
return result

n° 161

Réalisation de tri
 Python fournit une fonction native permettant de réaliser des tris :
listeEntiers = [ 5 , 1 , 2 , 4 , 3 ]
print (sorted ( listeEntiers))
print(listeEntiers)

 Il existe aussi une méthode sort que l’on peut appliquer sur les listes:

listeEntiers = [5, 1, 2, 4, 3]
listeEntiers.sort()
print ( listeEntiers)

 La fonction «sorted» génère une nouvelle liste alors que la méthode sort()
modifie la liste d’origine
 Il est possible de définir la façon de trier avec le paramètre reverse qui est un
booléen pour déterminer si on veut un tri ascendant ou descendant

n° 162

81
Tri sur les collections d’objets
 Que se passe t’il lorsque l’on veut trier une liste de Comptes

self.__liste_personnes.sort()

 Pour trier des personnes, il faut pouvoir les comparer. La classe personne doit
implémenter l’opérateur de comparaison :

def __gt__(self , pers):


return self.__age > pers.__age

 Problème : Le tri se fait toujours sur le même critère.

n° 163

__()).

Personnaliser son tri


 Il est possible de passer en paramètre une fonction de comparaison à l’aide
du paramètre cmp :
 Cette fonction doit prendre deux arguments à comparer :

def compare_personne(pers1, pers2):


return pers1.get_age() - pers2.get_age()
self.__liste_personnes.sort(cmp = compare_personne))

 A partir de Python 3, le paramètre cmp a été supprimé pour simplifier et


unifier le langage.
 Pour effectuer un tri en fournissant la méthode de comparaison, on va
utiliser le paramètre key et utiliser la méthode cmp_to_key.

self.__liste_personnes.sort(key=cmp_to_key(compare_personne))

n° 164

82
__()).

Personnaliser son tri


 Il est possible de fournir directement une méthode au paramètre key :
 La valeur du paramètre key doit être une fonction qui prend un seul argument
et renvoie une clef à utiliser à des fins de tri.
 Cette technique est rapide car la fonction clef est appelée exactement une
seule fois pour chaque enregistrement en entrée.

def compare_personne(pers : Personne ) -> int :


return pers1.get_age()

self.__liste_personnes.sort(cmp = compare_personne))

n° 165

Les dictionnaires
 Un dictionnaire permet de stocker des objets en les associant à une clé qui
doit être unique.
 La mise en œuvre se réaliser avec les {}

def test_dic():
un_dico = {"un":1 , "deux":2 , "trois":3 , "quatre":4 }
autre_dico = dict()
print ( type ( un_dico))
print ( un_dico["trois"])
print ( un_dico.get("trois"))
un_dico["cinq"] = 5
del un_dico["trois"]
print(un_dico)
for elem in un_dico :
print ( elem)
for cle , valeur in un_dico.items():
print ( cle , "=" , valeur )

n° 166

83
Module 10
Gestion du système

n° 167

Introduction
 La bibliothèque standard de Python est un élément incontournable de la
technologie !
 En effet, c’est elle qui apporte les fonctionnalités à Python.
 Il est bien entendu essentiel de bien connaitre le langage et sa syntaxe pour
pouvoir utiliser ces fonctionnalités.
 La documentation officielle de Python, propose une référence exhaustive de
ces fonctionnalités, agrémentée de nombreux exemples d’utilisation.
 https://docs.python.org/3/library/index.html

n° 168

84
La gestion des dates
 Python fournit plusieurs modules pour la gestion de date :
 time: module qui fournît des fonctions et des constantes liées à la date et à
l’heure.
 Datetime: module objet qui propose différentes classes pour la gestion de la
date et de l’heure
 Calendar: module qui fournît des fonctions et des classes pour la gestion de
calendrier.
 Locale: module qui contient des fonctions qui sont utilisées pour le formatage
ou l’analyse de la date et de l’heure en fonction des paramètres régionaux.

n° 169

Le module datetime
 Le module « datetime » est conçu sur la base d’objet pour fonctionner avec
la date et l’heure. Il contient un ensemble de classes :
 date : représente une date selon le calendrier grégorien
 datetime: : représente une date et une heure
 time : représente le temps
 tzinfo: classe abstraite qui sert de la classe de base pour la classe timezone
 timezone : représente le temps universel
 timedelta : représente une duration (durée) à savoir le delta entre deux dates.

n° 170

85
La classe Date
 Elle représente une date sous la forme aaaa/mm/jj :

def testDate():
today = date.today()
d = date(2020, 1, 1)
annee = d.year
mois = d.month
jour = d.day
print(f"{jour} {mois} {annee}")
print(d.strftime("%d/%m/%y"))
print(d.strftime("%A %d %B %Y"))

 La classe datetime représente une date et une heure et propose des


méthodes similaires.

n° 171

La classe Date
 Il est possible d’utiliser les opérateurs sur les dates:

def testManipDate():
today = date.today()
d = date(2020, 1, 1)
print ( today == d)
print ( today > d)
print ( today < d )
duree = (today - d)
print(type(duree) , " " , duree)
d2 = timedelta(days=3)
after = d + d2
print(after)

n° 172

86
Les expressions régulières
 Les expressions régulières sont des schémas ou des motifs utilisés pour
effectuer des recherches et des remplacements dans des chaines de
caractères.
 Ces schémas ou motifs sont tout simplement des séquences de caractères
dont certains vont disposer de significations spéciales et qui vont nous servir
de schéma de recherche.
 Les expressions régulières vont nous permettre de:
 vérifier la présence de certains caractères ou suite de caractères dans une
expression.
 d’extraire des valeurs
 de substituer des valeurs

n° 173

Le module re
 Le module « re » a été spécialement conçu pour travailler avec les
expressions régulières.
 Il définit plusieurs fonctions utiles ainsi que des objets propres pour
modéliser des expressions.
 La fonction match permet de vérifier si une expression correspond à un
motif:

def testMatch():
motif = r "^\d{2}$"
chaine = "10"
res = re.match(motif , chaine)
print (res.group(0)) #renvoie la chaine correspondant à la re
if res :
print ("format numerique ok")
else :
print ("format incorrect")

n° 174

87
Les expressions régulières
 Il existe un grand nombre d’expressions :

symbole signification
. N’importe quel caractère
[xy] Liste de valeurs possible
[x-y] Intervalle de valeur possible
[x|y] Choix de valeurs ( ou )
\d désigne tout chiffre équivalent à [0-9]
\D Pas de chiffre équivalent à [^0-9]
\w Présence alphanumérique idem [a-zA-Z0_9_]
\W Pas de caractère alphanumérique
\s Présence d’un espace [ \t\n\r\f\v]
\S Pas d’espace
^ Début ou contraire de
$ Fin de segment
n° 175

Les multiplicateurs
 Il permette de définir un nombre de fois ou l’expression est attendue:

symbole signification

* Présence entre 0 et n fois

1 Présence de 1 à n fois

? Présence de 0 à 1 fois

{m,n} Choix de valeurs ( ou )

(?!(…)) Absence du groupe désigné par les points de suspension

n° 176

88
L’instruction compile
 Une expression régulière produit en interne une machine à état:
 Cette machine à état évolue au fur et à mesure du traitement de la chaîne de
caractères
 Si on utilise une expression régulière fréquemment, il peut être intéressant
d’optimiser le traitement en la compilant à l’aide de la méthode compile

def testCompile():
regex = re.compile(r"^\d{2}$")
chaine = "111"
res = regex.match (chaine)
if res :
print ('format numerique ok ')
else :
print ('format incorrect')

n° 177

Les fonctions du module re


 Le module « re » fournit un ensemble d’autre fonctionnalités:
 match (s [,pos[,end]]) : Vérifie la correspondance entre l’expression régulière
et la chaîne s. Il est possible de n’effectuer cette vérification qu’entre les
caractères dont les positions sont pos et end. La fonction retourne None s’il
n’y a pas de correspondance et sinon un objet de type Match.
 search (s [,pos[,end]]) idem match, au lieu de vérifier la correspondance entre
toute la chaîne et l’expression régulière, cherche la première chaîne de
caractères extraite correspondant à l’expression régulière.
 split (s [,pos[,end]]) : Recherche toutes les chaînes de caractères extraites qui
vérifient l’expression régulière puis découpe cette chaîne en fonction des
expressions trouvées.
 findall(s[, pos[, end]]): recherche les chaînes correspondant aux motifs.
def testFindAll():
res = re.findall("([0-9]+)", \
"cours Python le 10 janvier et le 17 janvier")
print (res ) #['10', '17']

n° 178

89
Interaction avec le système d’exploitation
 Python propose un module de bas niveau pour appréhender son système
d’exploitation.
 Le module os
 Les différentes fonctions et constantes présentes dans ce modules
permettent de collecter des informations sur son système d’exploitation.

n° 179

Collecter des informations sur le système


 Avec le module os, il est donc possible :
 D’identifier les caractéristiques de son système d’exploitation :
 os.name
 De trouver la liste des variables d’environnement :
 list(os.environ.keys())
 De récupérer le répertoire courant
 os.getcwd()
 D’obtenir les valeurs de constantes types du système :
 os.curdir, os.pardir
 os.sep, os.pathsep, os.linesep
o Les commandes précédentes sous Windows :

n° 180

90
Interagir avec les processus
 Python permet également, grâce aux modules os et subprocess, de lancer
des commandes du système d’exploitation.
 Lancer une commande et afficher son résultat :

os.system("dir")

subprocess.call("dir /p", shell=True) version historique

subprocess.run("dir /p", shell=True) version 3.5

Subprocess.Popen(["dir", "/p" ], shell=True )


# plus riche en fonctionnalités

 La variable retour contiendra le code de retour de la commande (0 si tout va


bien)
 Il faut spécifier l’argument shell à true pour les commandes internes

n° 181

Interagir avec les processus


 Lancer une commande et récupérer son résultat :
 retour, resultat = subprocess.getstatusoutput(['ls', '-l'])
 La fonction renvoie un tuple. La variable retour contient le code de retour de
la commande, la variable resultat contient le résultat produit par la
commande sur la sortie standard
 On peut rediriger une commande vers une autre commande à l’aide de
l’instruction popen :

def testPipe():
p1 = subprocess.Popen(["dir"], stdout=subprocess.PIPE, shell=True)
p2 = subprocess.Popen(["findstr", 'py'], stdin=p1.stdout,
stdout=subprocess.PIPE, shell=True)
p1.stdout.close()
output, err = p2.communicate()
print(output)

n° 182

91
)
Travailler avec les chemins d’accès
 Le module os propose un ensemble de méthodes pour manipuler les fichiers à
travers le chemin d’accès
 os.listdir(rep)
 os.path.exists(fic1)
 os.path.isfile(fic1)
 os.path.isdir(fic1)
 La manipulation des chemins avec le module de bas niveau os, est assez
archaïque !
 Dans le cas ou l’on veut gérer des chemins multiplateforme, il faut construire les
chemins en tenant compte de la spécificité du séparateur de chemin en vigueur
sur chaque systèmes !
chemin = "rep1" + os.sep + "rep2" + os.sep + "rep3"

 Pour construite le chemin « rep1/rep2/rep3».


 Peu lisible !
 Le module de haut niveau pathlib permet d’apporter ces fonctionnalités.

n° 183

Le module pathlib
 Le module pathlib permet une gestion de haut niveau du système de
fichiers, permettant ainsi une manipulation aisée des chemins, des
répertoires et des fichiers.
 La classe Path constitue le principal élément de ce module. Elle permet
l’expression de chemins et leur manipulation.

from pathlib import *


path = Path(".")

 Une fois l’objet de type Path créé, des méthodes permettent de manipuler la
référence de chemin ainsi créée.
def chemin() :
chemin = "rep1" + os.pathsep + "rep2" + os.pathsep + "rep3"
path = Path(".")
path.is_dir()
path.is_file()
path.absolute()

n° 184

92
Manipuler les fichiers et les répertoires
 Python étant à l’origine conçu pour réaliser des opérations système, il est
naturellement pourvu d’outils très simples d’utilisation pour manipuler des
fichiers.
 Ces fonctionnalités de base font partis des « Buildin » il n’est pas nécessaire
de devoir importer un quelconque module pour pouvoir les utiliser.
 La fonction d’ouverture de fichiers possède la signature suivante :
open(file, mode='r')
 Le premier paramètre est le fichier à ouvrir,
 le second son mode d’ouverture (r étant pour read, par défaut)
 La fonction open renvoie un objet qui représente le fichier
 L’objet est de type _io.TextIOWrapper
 Le fichier doit être fermé à l’aide de la méthode close()
idFile.close()

n° 185

Les modes d’ouvertures de la fonction open


 La langage fournit un ensemble de mode d’ouverture :

Caractère Signification

‘r’ Ouverture en lecture (par défaut).

‘w’ Ouverture en écriture, le fichier est d’abord vidé.

‘x’ Ouverture pour création. Une erreur est générée si le fichier existe.

‘a’ Ouverture en écriture, le contenu est ajouté au contenu éventuellement


existant.

‘b’ Mode binaire.

‘t’ Mode texte (par défaut).

‘+’ Ouverture pour mise à jour (lecture/écriture).

n° 186

93
Lire et écrire dans un fichier
 Une fois le fichier ouvert (dans le bon mode !), il est possible d’écrire et de
lire à l’intérieur.
 L’écriture se réalise avec les méthodes write et writelines :

def ecrire_fichier ():


lignes = ["Ligne1\n", "Ligne2\n", "Ligne3\n"]
fic = open("C:\\temp\\fic.txt", 'w')
fic.writelines(lignes)
fic.close()

 La lecture se réalise à l’aide des méthodes read et readlines


def lire_fichier ():
fic = open("C:\\temp\\fic.txt")
lignes = fic.readlines()
for ligne in lignes:
print(ligne, end='')
fic.close()

n° 187

Manipuler les fichiers et les répertoires


 Une autre solution consiste à utiliser l’instruction with:
ef ecrireV2():
lignes = ["Ligne1\n", "Ligne2\n", "Ligne3\n"]
with open("C:\\temp\\fic.txt", 'w') as fic:
fic.writelines(lignes)

 La variable fichier est alors un descripteur sur le fichier. Ce descripteur sera


fermé automatiquement fermé à la fin du bloc with.

def lireV2():
with open("C:\\temp\\fic.txt") as fic :
lignes = fic.readlines()
for ligne in lignes:
print(ligne, end='')

n° 188

94
Accès direct
 Il est possible d’ accéder à des fichiers en mode binaire en utilisant les
modes rb ou wb.
 Dans ce cas vous pouvez réaliser des accès directs à l’aide de la méthode
seek :
seek ( offset , base )

 Positionne le curseur à l’endroit demandé en fonction de la base qui peut


prendre trois valeurs :
 SEEK_SET(0): début du fichier
 SEEK_CUR(1): position courante
 SEEK_END (2): fin du fichier
 La fonction tell() renvoie la position du curseur de lecture par rapport au
début du fichier.

n° 189

Manipuler des fichiers avec pathlib


 La classe Path du module pathlib offre les mêmes fonctions de manipulation
de fichier que les primitives du langage.
 open(), read(), write(), …
 La manipulation de fichiers en lecture et écriture se fait donc « presque »
comme précédemment.
 La méthode s’appliquant à une référence de fichier, il n’est donc pas
nécessaire de spécifier ce dernier en premier paramètre.

def ecrireV3():
chemin = Path()/"data/files"
fichier = chemin/"datafile3.txt"
if not chemin.exists():
chemin.mkdir(parents=True)
lignes = ["Ligne1\n", "Ligne2\n", "Ligne3\n"]
with fichier.open('w') as fic:
fic.writelines(lignes)

n° 190

95
Manipuler des fichiers csv
 Python fournit le module pour effectuer des traitement sur des fichiers CSV
(Comma Separated Values):
 Fichiers textes pour lesquels chaque ligne est constitué de colonne séparé
par un caractère donné;
 Le caractère de séparation par défaut est la virgule
 Certains outils type tableur préfère utiliser le point virgule
 Pour créer un fichier csv, vous devez utiliser une instance de writer
def ecrireFormatcsv():
lignes = ["Ligne1", "Ligne2", "Ligne3"]
chemin = Path()/"temp"
fichier = chemin/"fic.csv"
fic = open(fichier, "a", newline="")
c = csv.writer(fic, delimiter=";")
for l in lignes:
c.writerow(l)
fic.close()

n° 191

Lecture d’un fichiers csv


 Pour lire un fichier csv, vous devez utiliser une instance de « reader »

def lireFormatcsv():
chemin = Path()/"temp"
fichier = chemin/"fic3.csv"
fic = open(fichier, "r", newline="")
lignes = csv.reader(fic, delimiter=";")
for l in lignes:
print(l)

 Python fournit de la même façon un module json permettant de gérer des


fichiers au format json.

n° 192

96
La sérialisation
 La sérialisation est le processus qui permet de convertir un objet en un flux.
 Il est alors possible de l’enregistrer dans un fichier, ou de le transmettre à une
autre application.
 La récupération de ce flux et sa transformation en objet sont appelées la
désérialisation.
 Le framework met à disposition trois techniques :
 Sérialisation binaire : module pickle
 Sérialisation Json : module json
 Sérialisation XMl : a chercher !

n° 193

Exemple
 Utilisation de deux classes : Pickler et Unpickler

def testSerialisation(nomfichier, obj):


buffer = Path() / nomfichier
f = open(buffer, 'wb')
pickler = pickle.Pickler(f, pickle.HIGHEST_PROTOCOL)
pickler.dump(obj)
f.close()

def testDeserialisation(nomfichier):
buffer = Path() / nomfichier
f = open(buffer, 'rb')
pickler = pickle.Unpickler(f)
obj = pickler.load()
return obj

n° 194

97
Module 11
Accéder aux bases de données avec
Python

n° 195

Présentation
 Python fournit des modules permettant de travailler avec des bases de
données :
 sqlite3 permet de travailler avec SQlite
 SQlite est SGBD léger :
 Utilise un sous ensemble de SQL
 Les données se trouvent sur le terminal du client et non sur un serveur distant
 Outil apprécié pour les applications embarquées
 Intégré nativement à Python

n° 196

98
Connexion à la base
 La méthode «connect» permet de nous connecter à une base :

import sqlite3
connection = sqlite3.connect(nameBd)

 Si le fichier .db n’existe pas alors il sera créé.


 La fonction renvoie un objet de type Connection qui nous permettra de
travailler avec la base.

 Pour se déconnecter à la base, il faut utiliser l’instruction deconnect()

connection.close()

n° 197

Authentification
 Sqlilte ne propose pas de mécanisme d’authentification par défaut. Il est
possible d’activer ce mécanisme
 inclure le fichier de code source ext/userauth/userauth.c dans la génération
 ajouter l'option de compilation DSQLITE_USER_AUTHENTICATION.
 Il est aussi possible de stocker la BDD directement dans la RAM en utilisant la
chaîne clef ":memory:".
 dans ce cas, il n’y a pas de persistance des données après la déconnexion.
 Utiliser pour effectuer des tests qui sont ainsi reproductibles et n’altèrent pas
d’éventuelles BDD persistantes.

n° 198

99
Exécution de requêtes
 L’ exécution des requêtes se réalisent à l’aide de la méthode «execute» sur
un objet Cursor:
 Un objet cursor se récupère suite à l’appel de la méthode cursor sur l’objet
de type Connection

import sqlite3

def create_table(nameBd):
connection = sqlite3.connect(nameBd)
cursor = connection.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS personnes(
id INTEGER PRIMARY KEY,
nom TEXT, prenom TEXT, email TEXT ) """)
connection.commit()
connection.close()

n° 199

Validation des données


 Lorsque nous effectuons des modifications sur une table (insertion,
modification ou encore suppression d’éléments), celles-ci ne sont pas
automatiquement validées :
 La méthode commit() permet de valider la requête.
 La méthode rollback() permet d’invalider une requête et de revenir à l’état
précédent.

n° 200

100
Paramétrage de requêtes
 L’insertion en base se fait par une requête SQL :

cursor.execute("""INSERT INTO personnes(nom, prenom , email)


VALUES( 'nom1', 'prenom1' , 'email1') """)

 Pour éviter les injections SQL il faut paramétrer les requêtes:

cursor.execute("""INSERT INTO personnes(nom, prenom , email)


VALUES(?, ?, ?)""", ("nom2", "prenom2", "email2"))

n° 201

..

Récupération de données
 Pour récupérer des éléments, il faut effectuer une requête Sql puis parcourir
le résultat à l’aide de l’objet Cursor:
 fetchone permet de récupérer un élément sous forme de tuple ou none si il
n’y en a pas.
 fetchall permet de récupérer l’ensemble des résultats.
 fetchmany permet de récupérer plusieurs résultats.
o Le nombre de résultat par défaut correspond à la valeur de l’attribut arraysize
du curseur.
o On peut passer le nombre voulu en paramètre

def get_user(nameBd, name):


connection = sqlite3.connect(nameBd)
cursor = connection.cursor()
cursor.execute("""SELECT nom, prenom , email FROM personnes
WHERE nom=? """, (name,))
user = cursor.fetchone()
connection.close()
return user
n° 202

101
Gestion des erreurs
 La manipulation des données en base peut engendrer des erreurs. Il faut les
traiter à l’aide des exceptions :
def create_table(nameBd):
try:
connection = sqlite3.connect(nameBd)
cursor = connection.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS personnes(
id INTEGER PRIMARY KEY,
nom TEXT, prenom TEXT, email TEXT ) """)
connection.commit()
except sqlite3.Error as ex:
connection.rollback()
print(ex)
finally:
if connection:
connection.close()

n° 203

Utilisation des base de données


 Il est possible de travailler avec d’autres bases de données :
 Il faut récupérer le driver de la base de donnée
 Pour utiliser par Mysql il faut réaliser les installations suivantes :
 pip install mysql
 pip install mysql-connector-python

def createTableMysql():
connection = mysql.connector.connect(host="localhost",
user="root",
password="root",
database="bdUsers")
auth_plugin="mysql_native_password"
cursor = connection.cursor()

n° 204

102
Les ORM
 Il existe plusieurs ORM pour python :
 SQLAlchemy : le plus connu et le plus utilisé
 Peewee : simple et efficace
 Pony ORM
 SLQAlchemy est une ORM codé en python :
 Il apporte un haut niveau d’abstraction
 Il n’y a plus besoin de réaliser de requêtes SQL
 Ce module doit être installé explicitement

n° 205

Fin de la formation

Programmer en Python

n° 206

103

Vous aimerez peut-être aussi