Académique Documents
Professionnel Documents
Culture Documents
Adel KHALFALLAH
Institut Supérieur d’Informatique
Adel.Khalfallah@isi.utm.tn
1
Objets – Valeurs - Types
• Toutes les données sont représentées par des objets
– A chaque valeur, il correspond un objet
i=5
– 5 est un objet référencé par i
j=i
– i et j référencent le même objet
– id(5), id(i), id(j) donnent la même valeur, l’identifiant unique de
l’objet 5
– i is j retourne true
– a = 1; b = a id(a), id(b) et id(1) sont les mêmes
– a = a +1, id(a) != id(b) et id(a) = id(2) d’une part et id(b) = id(1)
d’autre part
2
Objets – Valeurs - Types
• le type bool
– 2 valeurs uniquement : True et False
– sous type de int donc conversion implicite
– i=123
– j=i + True
– print(j) -> 124
3
Objets – Valeurs - Types
• Le type Entier: int
– le domaine n’est pas fixe, il dépend de la mémoire disponible
4
Objets – Valeurs - Types
• complexe : complex
– les valeurs sont des couples de réels de la forme u + vj
5
Objets – Valeurs - Types
• Chaines de caractères: str
– Il n’y a pas de type caractère, chaine de longueur 1
6
Objets – Valeurs - Types
• Intervalle: range
– Un intervalle est défini par une borne inférieure, une
borne supérieure et un pas: r=range(0,10,1)
– Le dernier élément de l’intervalle est strictement
inférieur à la borne supérieure
– par défaut le pas et 1 (il ne peut pas être 0) et la borne
inférieure 0; r=range(10)
– r[i] permet d’accéder à l’élément de l’intervalle de
numéro i, la numérotation commence à 0, inversement
index permet de retrouver le numéro d’un élément de
l’intervalle. r=range(0,10,2); r[1] -> 2; r.index(2) -> 1
7
Objets – Valeurs - Types
• Listes : list
– Les listes sont des containers hétérogènes: ils regroupent des
éléments de différents types
8
Objets – Valeurs - Types
• n-uplet: tuple
– Les n-uplets sont des containers hétérogènes: ils
regroupent des éléments de différents types
X = 1,’a’,[2] ou X = (1,’a’,[2])
9
Objets – Valeurs - Types
• str, list, et tuple implantent une interface commune
– x in s True if an item of s is equal to x, else False
– x not in s False if an item of s is equal to x, else True
– s + t the concatenation of s and t
– s * n or n * s equivalent to adding s to itself n times
– s[i] ith item of s, origin 0
– s[i:j] slice of s from i to j
– s[i:j:k] slice of s from i to j with step k
– len(s) length of s
– min(s) smallest item of s
– max(s) largest item of s
– s.index(x[, i[, j]]) index of the first occurrence of x in s (at or after index i and before
index j)
– s.count(x) total number of occurrences of x in s
10
Objets – Valeurs - Types
• Ensembles: set
– Les types hashable sont: int , float , str , tuple , and NoneType
– Un ensemble regroupe des valeurs de type hashable sans
répétition.
E = {1, ‘a’,(2,3)}
– Ils peuvent être générés à partir d’un intervalle
– La position dans l’ensemble n’est pas significative E1={1,2};
E2={2,1}; E1==E2 -> True
– Les ensembles offrent l’addition, la suppression et les opérations
usuelles, union, intersection,…
11
Objets – Valeurs - Types
• Table: dict
– Associe des clés (hashable) à des objets:
d = {‘one’ : 1, 2: ‘deux’, ‘three’ : [3]}
– list(d) retourne la liste des clés, d[clé] retourne l’objet
associé à la clé, …
– keys et values sont des vues dynamiques sur les clés
et les valeurs
v=d.keys(); d[‘four’] = 4;
print(v) ->[‘one’, 2, ‘three’, ‘four’]
12
Objets – Valeurs - Types
• Immutable: sémantique par valeur/copie
– Numbers (Integer, Rational, Float, Decimal, Complex &
Booleans)
– Strings, Tuples, Frozen Sets, Ranges
– Exemple: i=123; j=i; id(i)=id(j); i=i+1; id(i)=id(124);
print(j) -> 123; id(j) != id(i)
• Mutable: sémantique par réference/partage
– Lists, Sets, Dictionaries
– Exemple L=[1,2,3]; L1=L; L.append(4);
print(L1) ->[1,2,3,4]; id(L)=id(L1)
13
operateur d’affectation
• := est un opérateur binaire
– l’opérande gauche est une variable
– l’opérande droit est une expression
– le résultat de var:=expression est le résultat de expression
• Exemple:
A=1
B=(C:=A+1)
print("A = ",A,"B = ",B,"C = ",C)
-> A = 1 B = 2 C = 2
14
operateur conditionnel
• expr1 if cond else expr2
– cond est évalué
– s’il est vrai le résultat est expr1
– sinon le résultat est expr2
• Exemple
a=1
b=2
c= 3
15
Instructions: Affectation
• Basic assignement:
var = expr Exemple: a=2
• Tuple assignement
var1, var2,…,varn=(v1,v2,…,vn) Exemple a,b=(2,3)
• List assignement
var1, var2,…,varn=[v1,v2,…,vn] Exemple a,b=[2,3]
• Sequence assignement
var1, var2,…,varn= v1,v2,…,vn Exemple a,b=2,3
• String assignement
var1, var2,…,varn= ‘’v1v2…vn‘’ Exemple a,b=‘’Hi’’
• Range assignement
var1, var2,…,varn= range(n) Exemple a,b=range(2)
16
Instructions: Affectation
• Extended sequence assignement
– var1, var2,…,*varp= v1,v2,…,vn et p < n
var1 -> v1, var2 -> v2,…,varp-1 ->vp-1, varp->[vp,vp+1,…vn]
Exemple a,b,*c=1,2,3,4,5,6 c ->[3,4,5,6]
– S’applique à list, tuple, string, range
17
Instructions: Affectation
• Augmented assignement
– var op= expression
– op: + - * / // (division entière) %(modulo) **(puissance) &
(et bit à bit) | ( ou bit à bit) ^(xor bit à bit) <<(shift gauche)
>> (shift droit)
18
Instructions : Conditionnelles
• if Expression_booléenne:
instructions
• if Expression_booléenne:
instructions
else :
instructions
• if Expression_booléenne:
instructions
elif Expression_booléenne :
instructions
elif Expression_booléenne :
instructions
…
else:
instructions
19
Instructions : Conditionnelles
a=float(input()); b=float(input()); c=float(input())
if a==0:
if b==0:
if c==0:
print('R')
else:
print("impossible")
else:
print('simpl x= ',-c/b)
else:
delta=b**2-4*a*c
if delta==0:
print('double x= ',-b/(2*a))
elif delta < 0:
print('mpossible dans R')
else:
print('x1= ',(-b-(delta)**0.5)/(2*a),'x2= ',(-b+(delta)**0.5)/(2*a))
20
Instructions : Conditionnelles
• match subject:
case pattern :
instruction
case pattern if condition :
instruction
case _:
instruction_defaut
• subject peut-être une variable, un tuple ou une liste
• pattern peut être :
– un littéral ou _
– un tuple ou une liste de littéraux
– un tuple ou une liste comportant des variables ou des variables étoilées, les variables seront
liées aux éléments du subject de même position:
u=0; v=123
match (u,v):
case (0,u) -> u est v
print(u) -> 123
21
Instructions : Conditionnelles
a=float(input()); b=float(input()); c=float(input())
match (a,b,c):
case (0,0,0):
print("R")
case (0,0,_):
print("Impossible")
case(0,_,_):
print("x= ",-c/b)
case(_,_,_) if ((b**2-4*a*c)==0):
print("x =",-b/(2*a))
case(_,_,_) if (delta:=(b**2-4*a*c)>0):
print("x1 =",(-b-delta**0.5)/(2*a),"x2 =",(-b+delta**0.5)/(2*a))
case _ :
print('impossible dans R')
22
Instructions : Itérations
• while Expression_booléenne:
instructions
else:
instructions
l=[7,22,87,13]
ind=0; trouve=False
while ind<len(l) and not trouve:
if not (trouve:= (l[ind] % 3) == 0):
ind+=1
else:
if trouve:
print(l[ind])
23
Instructions : Itérations
• for target_list in expression_list:
instructions
else:
instructions
• expression_list est évaluée elle doit correspondre à un
itérable (range, liste, ensemble,…)
• target est une ou plusieurs variable, à chaque variable il
doit correspondre un itérable
TDS={'i':'int','x':'float','z':'complex'}
for var,sontype in TDS.items():
print(var,sontype)
24
fonctions et procédures
• def NomFunction(paramètres):
• paramètres peuvent être typés
def Equ2ndDeg(a,b,c) ou
def Equ2ndDeg(a:float, b: float, c:float)
• Le type de retour peut être explicité
def factoriel( N : int) -> int
• L’appel peut utiliser la position ou le nom pour les
paramètres
Equ2ndDeg(1,2,1) ou
Equ2ndDeg(b=2, c=1,a=1)
25
fonctions et procédures
• Les paramètres peuvent avoir une valeur par défaut, tous
les paramètres qui ont une valeur par défaut sont groupés
à droite
def convertit(valeur,base=8):
• Le nombre de paramètres peut être variable, le nombre
de résultats aussi
def moyenne(Nom,*Notes):
total=0
cpt=0
for note in Notes:
total+=note
cpt+=1
return Nom, total/cpt
26
fonctions et procédures
• Mode de passage de paramètres:
– Les objets immutables se comportent comme un passage par
valeur
def valeur(x):
print("x=",x," id=",id(x))
x=321
print("x=",x," id=",id(x))
27
fonctions et procédures
• Mode de passage de paramètres:
– Les objets mutables se comportent comme un passage par
référence
def reference(villes):
villes.append("Gabes")
>> mesVilles = [‘Tunis’, ‘Sousse’,’Sfax’]
>>reference(mesVilles)
>>mesVilles -> [‘Tunis’, ‘Sousse’,’Sfax’, ‘Gabes’]
28
fonctions et procédures
• Mode de passage de paramètres
– La référence est passée par valeur
grand=[111,222,333]
def valeur(liste):
liste=grand
print(liste)
>>maListe=[1,2,3]
>>valeur(maListe) ->[111,222,333]
>>maListe -> [1,2,3]
29
Programmation Objet: Classes
• Une classe est un regroupement de données et de
traitements. Elle est définie par le mot clé class
class Hello:
Comportement
Etat
30
Programmation Objet: Construction
• Pour obtenir un objet, il est nécessaire d’initialiser son
état. Par exemple, un objet personne a dans son état son
âge.
• Pour chaque nouvel objet personne, l'âge doit être
initialisé à zéro
• __init__ est le constructeur, c’est une méthode qui est
invoquée implicitement pour chaque nouvel objet. Le
premier paramètre est impérativement l’instance pour
laquelle l’initialisation a lieu, on convient de l’appeler self
31
Programmation Objet: Construction
class Personne:
def __init__(self):
self.age=0;
• Pour créer un objet, on passe par le nom de la classe
P=Personne()
32
Programmation Objet: Attributs
• L’état regroupe les données nécessaires au
fonctionnement de la classe, il est constitué d’attributs ou
de propriétés
• On distingue entre les attributs de classes et les attributs
d’instances:
– La valeur d’un attribut de classes est commune à toutes les
instances
– la valeur d’un attribut d’instance est propre à un objet
33
Programmation Objet: Attributs d’instance
• Une personne est définie par son nom, son âge et sa date
de naissance. Ces informations seront disponible
lorsqu’une méthode y fera référence:
class Personne:
def __init__(self):
self.age=0
def setNom(self,nom):
self.nom=nom
34
Programmation Objet: Attributs de classe
• Les attributs de classe sont communs à toutes les
instances, ils sont définis en dehors de toute méthode
class Personne:
Population=321
def __init__(self):
self.age=0
def setNom(self,nom):
self.nom=nom
>> Personne.Population -> 321
>>P=Personne(); P.Population ->321
35
Programmation Objet: Attributs de classe
• Attention à la portée:
class Personne:
Population=0
def __init__(self):
self.age=0
def setNom(self,nom):
self.nom=nom
Population=123 #locale à setNom
>>P=Personne()
>>P.Population -> 0
>>P.setNom(“Ali”)
>>P.Population -> 0
36
Programmation Objet: Attributs de classe
• Attention à la portée:
class Personne:
Population=123
>>P = Personne()
>>P.Population -> 123 #Attribut de classe
>>P.Population = 321 # Attribut d’instance propre à P
>>P1=Personne()
>>P1.Population -> 123 #Attribut de classe
>>P.Population -> 321 #Attribut d’instance
37
Programmation Objet : Méthodes
• Les méthodes manipulent l’état elles ont toutes self en
paramètre
class Personne:
def __init__(self):
self.age=0
def setNom(self,nom):
self.nom=nom
def Vieillir(self,duree):
self.age+=duree
38
Programmation Objet : Méthodes de classe
• Une méthode de classe reçoit une classe en paramètre.
Elle n’accède qu’aux attributs de classe, elle s’invoque
par rapport à la classe
class Personne:
Population=0
@classmethod
def IncPop(cls):
cls.Population+=1
>>Personne.IncPop()
>>Personne.Population -> 1
>>P=Personne(); P.IncPop(); Personne.Population -> 2
39
Programmation Objet : Méthodes statique
• Une méthode statique ne peut accéder ni aux attributs de
classe ni aux attributs d’instance, elle calcule son résultat
à partir de ses paramètres
class Personne:
@staticmethod
def estMajeur(age):
return age > 18
>>Personne.estMajeur(21) -> True
>>P=Personne()
>>P.estMajeur(15) -> False
40
Programmation Objet : __str__
• __str__ lorsqu’on veut convertir l’objet en chaine
class Personne:
Population=0
def __init__(self,nom,age):
self.age=age
self.nom=nom
def __str__(self):
return self.nom+" -- "+str(self.age)
>>P=Personne(‘’ali’’,20)
>>print(P) ali -- 20
41
Programmation Objet: Encapsulation
• Python n’offre pas de mécanisme pour interdire l’accès à
l’état
• Les attributs nommés avec __ en préfixe sont
automatiquement renommés par
_nomclasse__nomattribut
• C’est l’usage pour encapsuler les attributs et éviter l’accès
accidentel
42
Programmation Objet : propriétés
• Les propriétés permettent de contrôler l’accès à un
attribut sans pour autant imposer l’encapsulation
class compteur:
def __init__(self,val):
self._cpt=val;
def setCpt(self,val):
self._cpt=val
print("Ecriture")
def getCpt(self):
print("Lecture")
return self._cpt
def delCpt(self):
print("Suppression")
raise TypeError(" attribut non supprimable ")
cpt=property(getCpt,setCpt,delCpt,"Valeur du compteur")
43
Programmation Objet : propriétés
class compteur:
def __init__(self,val):
self._cpt=val;
@property
def cpt(self):
print("Lecture")
return self._cpt
@cpt.setter
def cpt(self,val):
self._cpt=val
print("Ecriture")
@cpt.deleter
def cpt(self):
print("Suppression")
raise TypeError(" attribut non supprimable ")
44
Programmation Objet : destruction
• del permet de détruire un objet, un attribut, une classe, …
class test:
def addAtr(self):
self.atr=123
>> x=test()
>>print(x.atr) => erreur
>>x.addAtr(); print(x.atr) => 123
>> del x.atr; print(x.atr) => erreur
• la definition de __del__ dans une classe, introduit un destructeur qui
est invoqué implicitement à chaque destruction d’objet
45
Programmation Objet : surcharge
• Surcharger consiste à utiliser le même nom pour des algorithmes
différents
• Python n’autorise pas directement la surcharge mais elle peut être
simulée grâce aux paramètres par défaut, le code devient surchargé
def min(a,b,c=None):
if (a <= b):
res=a
else:
res=b
if c == None:
return res
else:
if res <= c:
return res
else:
return c
46
Programmation Objet : surcharge des opérateurs
• Différents opérateurs peuvent être étendus aux classes utilisateurs, il
suffit de définir dans la classe une méthode correspondante
class Fraction:
def __init__(self,num,denom):
self.num=num
self.denom=denom
def __add__(self,F):
return
Fraction(self.num*F.denom+F.num*self.denom,self.denom*F.denom)
def __mul__(self,F):
return Fraction(self.num*F.num,self.denom*F.denom)
>>F1=Fraction(2,3), F2=Fraction(3,4), F3=F1+F2 =>17/12
>> F3=F1*F2
47
Programmation Objet : surcharge des opérateurs
Operateur Expression Interprétation Python
Addition p1 + p2 p1.__add__(p2)
Soustration p1 - p2 p1.__sub__(p2)
Multiplication p1 * p2 p1.__mul__(p2)
Puissance p1 ** p2 p1.__pow__(p2)
Division p1 / p2 p1.__truediv__(p2)
Division entière p1 // p2 p1.__floordiv__(p2)
le reste (modulo) p1 % p2 p1.__mod__(p2)
Décalage binaire gauche p1 << p2 p1.__lshift__(p2)
Décalage binaire droite p1 >> p2 p1.__rshift__(p2)
ET binaire p1 & p2 p1.__and__(p2)
OU binaire p1 | p2 p1.__or__(p2)
XOR p1 ^ p2 p1.__xor__(p2)
NON binaire ~p1 p1.__invert__()
48
Programmation Objet : surcharge des opérateurs
Operateur Expression Interprétation Python
Inférieur à p1 < p2 p1.__lt__(p2)
Inférieur ou égal p1 <= p2 p1.__le__(p2)
Egal p1 == p2 p1.__eq__(p2)
différent p1 != p2 p1.__ne__(p2)
Supérieur à p1 > p2 p1.__gt__(p2)
Supérieur ou égal p1 >= p2 p1.__ge__(p2)
49
Programmation Objet: Héritage
class Personne:
def __init(self,unNom):
self.nom=unNom
def veillir(self):
age+=1
Class Employe(Personne):
…
>>E=Employe()
>>E.nom=“Ali”
>>E.veillir()
50
Programmation Objet: Héritage - construction
• Pour initialiser Employe, il faut initialiser Personne
class Employe:
def __init__(self,nom,unSalaire):
super().__init(nom)__
self.salaire=unSalaire
51
Programmation Objet: Polymorphisme
• Surcharge, généricité, liaison dynamique
• Liaison dynamique élimine les instructions de type ‘switch’
• Le ‘duck typing’ de python laisse une grande liberté qui
risque d’ouvrir la porte à des erreurs
class Legume class Viande:
def decongeler(self): def decongeler(self):
def cuire(self) def cuire(self)
… …
class plat_vegetarien:
def ingredient(self,i):
i.decongeler()
i.cuire()
52
Programmation Objet: class abstraite
• Le module ABC (Abstract Base Class) permet de spécifier
des classes/méthodes abstraites
from abc import ABC, abstractmethod
class figure(ABC):
@abstractmethod
def dessiner(self):
pass
• Il ne sera pas possible d’instancier figure, les
descendants qui n’implantent pas dessiner ne pourront
pas aussi être instanciés
53
Les patrons de conception
54
Design Patterns
Design patterns
• Se Définissent par un nom
• Sont relatifs à un problème de conception récurrent
• Proposent une structure de solution qui pourra être mise
en œuvre à chaque occurrence du problème
55
Design patterns
• Proposition originale : 23 DP organisés en trois
catégories:
– DP créateurs : différentes façons de créer des objets (Fabrique
abstraite, Monteur, Méthode fabrique, Prototype, Singleton)
– DP Structuraux : Différents moyens de composer des objets pour
réaliser de nouvelles fonctionnalités (Adaptateur, Pont, Composite,
Décorateur, Façade, Poids Mouche, Procuration)
– DP de comportement : Différents moyen de communication et de
répartition du contrôle entre objets (Chaîne de responsabilité,
Commande, Interpréteur, Itérateur, Médiateur, Mémento, Observateur,
Etat, Stratégie, Patron de méthode, Visiteur)
• De nouveaux DP sont régulièrement proposés
56
Observateur
• Application qui collecte des données météo (température,
pression, humidité) et qui affiche différents résultats
(données collectées, statistiques, prévisions)
• L’affichage doit être asynchrone
• L’affichage doit être extensible
57
Observateur
getTemp AffStat
getPress Afficheur Stat
GetHum AffPrev
Afficheur Prév
58
Observateur
• Principe : Émetteur + Abonné
• Un objet (sujet) avec un état ‘intéressant’ est lié à plusieurs autres
(observateurs), un changement dans l’état de l’objet doit être notifié à
tous les observateurs.
Observable <<Interface>>
* Observateur
AddObs
SupObs Update
NotifyObs
SujetConc ObsConc
getState
SetState
59
Observable
class observable:
def __init__(self):
self.observateurs=[]
def add(o):
if not o in observateurs:
observateurs.append(o)
def remove(o):
if o in observateurs:
observateurs.remove(o)
def notify(data):
for o in observateurs:
o.update(data)
60
Observable concret
class sujet(Observable):
def __init__(self):
self.data=…
@property
def data(self):
return self.data
@data.setter
def data(newdata):
self.data=newdata
self.notify(newdata)
61
Observateur
• Le couplage est faible:
– Le sujet n’a aucune dépendance vis-à-vis des observateurs, il sait
uniquement qu’ils implantent la même interface (update). Il ne
dépend pas du type de l’observateur
– Le sujet ou l’observateur peuvent être réutilisés l’un
indépendamment de l’autre
• La gestion des observateurs est dynamique (Add,Supp)
• Le passage de l’état peut se faire selon différentes
politiques:
– Envoyés par le sujet lors de la notification: Certains observateurs
peuvent ne pas être intéressés par tout l’état
– Récupéré par les observateurs (facilite l’extensibilité du sujet):
risque d’avoir beaucoup d’appel à des getters
62
Model-View-Controller
• La partie GUI change fréquemment pendant la durée de
vie d’un système (portabilité, introduction de nouvelles
fonctionnalités,...).
• Les différents acteurs voient les données de façons
différentes
63
Model-View-Controller
Invoque des services
Lit des données
Contrôleur
Est un
Notification
Observateur Invoque des
Modèle services
Enregistrement
Est un
Vue
Lit des données
64
Model-View-Controller
I
Main
Créer Modèle
Créer Vue
Init(Modèle)
Enregistrer
Créer
Contrôleur
Init(Modèle,Vue)
Enregistrer
65
Model-View-Controller
II
Contrôleur Modèle Vue
Événement Service
Modification
de l’état
Notifier
Service
66
Model-View-Controller
• Les E/S doivent être soigneusement séparées des
traitements
• plusieurs formes
– Modèle attaché à plusieurs vue, toutes les vues rattachées à un
contrôleur
– Modèle attaché à plusieurs vue, chaque vue rattachée à un
contrôleur
– Modèle attaché à plusieurs vue, chaque vue rattachée à plusieurs
contrôleurs
• La gestion des vues et des contrôleurs peut-être statique
ou dynamique
67
Model-View-Controller
• La séparation entre la vue et le contrôleur est plus ou
moins forte : vue et contrôleurs peuvent être groupés
(Architecure Document-Vue de Windows et Xwindows)
• Il existe plusieurs frameworks qui offrent des vues et des
contrôleurs souvent structurés hiérarchiquement
68
Model-View-Controller
• Avantages:
– Indépendance par rapport à l’Interface utilisateur, plusieurs vues
pour le même modèle
– Interchangeabilité (éventuellement dynamique) des vues et des
contrôleurs
– Possibilité de disposer d’un framework pour les vues et les
contrôleurs
• Inconvénients
– Dans le cas d’applications offrant des interfaces simples on
aboutit à une complexité inutile
– Inefficacités dues à des notifications inutiles
– Les vues ne sont pas réutilisables sans leurs contrôleur (à
l’exception des vues qui ne modifient pas le modèle)
– La modification des interfaces du modèle a des conséquences sur
les vues et les contrôleurs
69