IGI-3008 – ESIEE Paris – 2016-2017
Programmation avec Python
TP8
Jean-Claude GEORGES
Programmation orientée objet en Python
Lors de ce TP, nous allons définir complètement une classe
Intervalle
permettant de
modéliser des
intervalles mathématiques fermés de réels strictement positifs
et de les
manipuler.
À la fin du TP, nous pourrons écrire des programmes du type :
>>> i1 = Intervalle(10.0, 12.0)
>>> i2 = Intervalle(9.0, 11.0)
>>> print(i1 & i2) # intersection
<10.0, 11.0>
>>> print(i1 + i2) # addition
<19.0, 23.0>
>>> if 20 in i1+i2:
print("Possible")
Définition d’une classe vide
Une classe peut être vue en première approche comme un type de données. Un
programmeur peut créer ses propres classes et les ajouter aux classes préexistantes de
Python (int list, etc.)
Figure 1— Une classe vide
class MaClasse(): # définition d'une classe "vide"
pass
a = MaClasse() # création d'un nouvel objet a
print(type(a)) # quel est le type de a ?
print(a) # qu'est ce que a ?
qui affichera :
<class '__main__.MaClasse'>
<__main__.MaClasse object at 0x0279A4F0>
Le programme de la figue 1crée une classe (vide). On peut instancier un élément de la
classe, vérifier qu’il existe et même l’afficher. Sans autre précision, l’affichage donne le nom
de la classe et l’adresse (en hexadécimal) de l’objet.
DÉFINITION DE LA CLASSE INTERVALLE 2
Définition de la classe Intervalle
Nous allons maintenant commencer l’écriture de la classe
Intervalle
. Pour cela, nous
nommons la classe avec un nom parlant (une convention respectée fait commencer les noms
de classe par une majuscule), et à l’intérieur de la définition, nous créons une méthode
magique de nom spécial __init__ qui permet d’initialiser les objets de cette classe.
Les méthodes magiques
Les méthodes magiques de Python sont des méthodes aux noms spéciaux
permettant aux classes utilisateur d’avoir le même comportement et la
même facilité d’utilisation que les classes prédéfinies.
Par exemple, si une classe
MaClasse
définit une méthode
__getitem__()
,
et si
x
est une instance de cette classe, alors l’utilisation de
x[i]
dans une
expression fera appel à MaClasse.__getitem__(x, i)
Ihttp://docs.python.org/3.4/reference/datamodel.html#
special-method-names
Ihttp://www.rafekettler.com/magicmethods.pdf
Un objet de la classe
Intervalle
contiendra deux données (attributs) : une borne
inférieure et une borne supérieure.
La méthode
__init__
aura donc trois paramètres : le premier étant l’objet que l’on
initialise (traditionnellement nommé
self
) et deux paramètres qui permettent d’initialiser
les bornes.
L’accès aux données d’un objet se fait par la notation pointée :nomObjet.nomAttribut
Exercice 1— Création de la classe Intervalle
Entrez le programme suivant : qu’affichera-t-il ?
class Intervalle:
def __init__(self, a, b):
self.borne_inf = a
self.borne_sup = b
a = Intervalle(2,3)
print(a)
print(a.borne_inf)
print(a.borne_sup)
TP8IGI-3008 (2016-2017)
PRÉPARATION EN VUE DE L’AFFICHAGE 3
Préparation en vue de l’affichage
Une méthode spéciale de nom (
__str__
) est utilisée par la fonction
str
(et par
print
)
pour donner une représentation utilisateur des objets sous forme de chaîne.
Une autre méthode spéciale de nom (
__repr__
) est utilisée par
repr
et par Python pour
une représentation "canonique" des objets sous forme de chaîne. La plupart du temps, on
aura : eval(repr(unObjet)) == unObjet
Comment fonctionne la fonction str de Python ?
Lorsque on invoque la fonction
str
sur un objet (
str(a)
), Python
recherche l’objet de nom
a
et regarde dans sa classe si une méthode
__str__(self)
est définie. Si oui, il l’appelle et retourne son résultat.
Sinon, il regarde dans sa classe parente, et remonte jusqu’à la classe mère
de toutes les classes : la classe prédéfinie
object
. Une méthode
__str__
est définie dans la classe object :
class object:# c'est pas le vrai, c'est juste pour expliquer
#....
def __str__(self):
""" str par défaut d'un objet sous la forme :
'<__main__.Classe object at 0x02E29D50>'
"""
s = '<'
s += self.__module__
s += +'.'
s += type(self).__name__
s += " object at "
s += "0x0"+hex(id(self)).upper()[2:]
s += '>'
#...
C’est elle qui est utilisée si la aucune méthode
__str__
n’est trouvée
avant.
Exercice 2— Affichage d’un Intervalle
Entrez le programme suivant : qu’affichera-t-il ?
class Intervalle:
def __init__(self, a, b):
self.borne_inf = a
self.borne_sup = b
def __str__(self):
return '<' + str(self.borne_inf)+ ', ' + str(self.borne_sup) + '>'
def __repr__(self):
return 'Intervalle(' + str(self)[1: -1] + ')'
a = Intervalle(2,3)
print(a)
aComment Python recherche-t-il les données ?
Lorsque un identificateur apparaît dans une expression, Python cherche
dans plusieurs dictionnaires de noms s’il est connu : d’abord dans
l’espace local (la fonction), puis l’espace parent, etc., jusqu’au niveau
principal du programme (
__main__
), puis aux noms prédéfinis. Dès qu’il
trouve un nom, c’est la donnée référée par ce nom qui est utilisée.
Les déclarations
nonlocal
et
global
devant un identificateur permettent
de modifier ce comportement par défaut.
TP8IGI-3008 (2016-2017)
SÉCURISATION MINIMALE 4
Sécurisation minimale
Les quatre exercices suivants ont pour objectif de sécuriser la classe
Intervalle
. Il s’agit
de ne pas avoir de donnée invalide dans un programme utilisant cette classe. Pour cela,
nous mettrons en œuvre la règle minimale : si l’on détecte une donnée fallacieuse, on
arrête le programme.
Évidemment, comme nous le verrons plus tard, Python permet de gérer de manière plus
élégante et moins brutale les erreurs.
Exercice 3— Quels problèmes de sécurité ?
Avec la classe
Intervalle
définie comme ci-dessus, entrez les lignes suivantes dans le
shell lancé :
>>> print(Intervalle(0.25, 0.3))
>>> print(Intervalle(0.35, 0.1))
>>> print(Intervalle("abc", [1,2,3]))
Que donneront les affichages ?
Exercice 4— Mettre les bornes dans l’ordre
Le second intervalle pose un problème : les bornes ne sont pas dans l’ordre. Cela peut
être corrigé par programme à l’initialisation (méthode
__init__
) : il suffit de stocker dans
borne_in f le plus petit de aet bet dans borne_sup le plus grand (utilisez min et max).
Modifiez la méthode
__init__
de la classe
Intervalle
pour qu’elle crée
automatiquement un intervalle dans le bon ordre.
TP8IGI-3008 (2016-2017)
SÉCURISATION MINIMALE 5
La création d’un intervalle avec une initialisation non numérique pose un problème plus
compliqué : on peut le corriger automatiquement s’il est possible de les
traduire
en
float
,
mais sinon on ne peut rien faire. La sécurisation minimale consiste à arrêter le programme
avec un message d’erreur.
Python permet d’
essayer
(
try
) des instruction et en cas d’erreur d’exécuter un gestionnaire
d’erreurs.
Ici, nous allons simplement arrêter le programme avec un message signalant l’erreur.
C’est la sécurité minimale. Il ne faudrait jamais qu’un programme continue son exécution
avec des données frelatées.
class Intervalle:
def __init__(self, a, b):
try:
a = float(a)
b = float(b)
except:
import sys
sys.exit("Problème d'init intervalle. On arrête tout")
self.borne_inf = min(a, b)
self.borne_sup = max(a, b)
def __str__(self):
return '<'+ str(self.borne_inf)+', '+str(self.borne_sup)+'>'
def __repr__(self):
return 'Intervalle(' + str(self)[1:-1] + ')'
print(Intervalle("0.35", 0.1)) # ça passe
print(Intervalle("0.35","a0")) # ça casse
print("On ne verra pas ce message (pgm s'arrêté avant)")
TP8IGI-3008 (2016-2017)
1 / 11 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !