Lyc´ee Thiers - MPSI-3

publicité
Lycée Thiers
COMPLÉMENTS DU COURS PYTHON - 01
Classes et modules : théorie et pratique
1. Rappel des épisodes précédents
Rappelons quelques informations que avons plus au moins rencontrées précédemment :
– Python est un langage orienté objets. On ne manipule que des objets ou des références d’objets.
– Les objets appartiennent à des classes (d’objets). Les classes elles mêmes sont des objets appartenant
à la classe type.
– Certaines de ces classes sont prédéfinies, comme les classes de nombres int, float ou les listes,
list etc...
– D’autres sont définies dans des fichiers appelés modules qu’il faut alors importer pour pouvoir les
utiliser. On peut définir ses propres modules.
– Enfin, on peut dans un script, définir des classes et les utiliser dans ce fichier.
Pour connaitre la classe d’un objet ou savoir si un objet appartient à une classe, Python propose deux
fonction : type et isinstance. Essayer dans le shell :
>>> type (2)
>>> isinstance ([1 ,2 ,3] , list)
>>> type( tuple )
>>> from math import sin
>>> type(sin)
>>> isinstance (int ,type)
2. Définir une classe : constructeur, attributs et méthodes
La définition d’un constructeur. Le mot réservé class suivi d’un identificateur permet de débuter
la définition d’une classe.
Comme pour une fonction, cette commande, suivie d’une instruction, suffit à définir une classe. Par
exemple :
class point2 :
""" Les objets de cette classe sont vides pour le moment """
suffit à définir une classe. Essayons :
COMPLÉMENTS DU COURS PYTHON - 01
2
>>> type( point2 )
>>> ? point2
Rem. Vous aurez remarqué l’indentation, indispensable, du bloc qui suit la première ligne de la
définition précédente.
En définissant une classe, on définit implicitement le constructeur de la classe. Essayer :
>>> P= point2 ()
>>> P
Le constructeur point2, qui porte le même nom que la classe, renvoie un objet de type point2 i.e.
une instance de la classe point2. Les parenthèses sont obligatoires. On verra dans la suite que l’on
peut modifier ce constructeur.
Les attributs ou membres d’une classe. Ce sont des sous objets de types déjà définis qui composent
notre objet plus complexe et que l’on va nommer. Par exemple, reprenons la définition de la classe
point2 :
class point2 :
""" Modélise les points d’un plan muni d’un repère """
x=None # première composante
y=None # deuxième composante
Exécuter ce script, puis dans le shell, saisir les commandes suivantes :
>>> ? point2
>>> P= point2 ()
>>> P.x
>>> P.x=2; P.y=3
>>> P.x+P.y
Les attributs d’un objet sont accessibles et modifiables après la construction de l’objet.
x et y sont les attributs de la classe point2 et des objets de cette classe. Il est toujours possible en
Python de définir après la définition d’une classe, des attributs pour un objet i.e. pour une instance
de cette classe. Essayer les instructions suivantes dans le shell :
>>> P.truc="ceci est un attribut d’instance "
>>> Q= point2 ()
>>> Q.truc
>>> Q=P
COMPLÉMENTS DU COURS PYTHON - 01
3
>>> Q.truc
>>> Q.truc=" je modifie l’attribut truc"
>>> P.truc
On distingue en Python deux types d’attributs : les attributs de classe qui existent chez tous les objets
d’une classe et les attributs d’instance qui sont définis après la construction d’un objet et qui peuvent
différer d’un objet à l’autre d’une même classe.
La souplesse de Python étant extréme :) et une classe étant aussi un objet, on peut manipuler les
attributs au niveau de la classe comme on le fait sur une instance de classe, avec bien entendu des
conséquences différentes. Essayer :
>>> point2 .x=0
>>> P= point2 ()
>>> P.x
>>> point2 . inutile ="rien"
>>> P. inutile
>>> Q= point2 ()
>>> Q. inutile
Malgré tout, il est préférable d’éviter ce genre de pratique. En programmation objet, la définition
d’une classe doit encapsuler tous les éléments qui définissent l’objet, en particulier ses attributs.
Les méthodes d’une classe. Il s’agit de fonctions que l’on explicite, en général, lors de la définition
de la classe et qui utilisent ou/et modifient, les objets de cette classe.
Elle comportent toutes au moins un paramètre qui sera remplacé lors de l’appel de la fonction par
l’objet lui-même. Dans le langage Python, on nomme habituellement ce paramètre self , sans que ce
soit une obligation. Tester le script suivant :
class point2 :
x=None
y=None
def initialise (self ,a,b):
self.x=a
self.y=b
P= point2 ()
P. initialise (1 , -1)
print (P.x,P.y)
COMPLÉMENTS DU COURS PYTHON - 01
4
Ajouter maintenant les lignes suivantes dans la définition de la classe point2 :
def estPlusMeridionalQue (self ,Q):
return self.y <=Q.y
def estPlusOccidentalQue (self ,Q):
return self.x <=Q.x
exécuter la cellule contenant la définition de la classe point2, puis exécuter les commandes qui suivent
dans le shell :
>>> P= point2 ();Q= point2 ()
>>> P. initialise (1 ,1);Q. initialise ( -1 ,4)
>>> P. estPlusMeridionalQue (Q)
>>> P. estPlusOccidentalQue (Q)
[Qu. 1]
1) Ajouter à la classe point2 une méthode echangexy qui échange les valeurs des attributs x et y
d’un objet de cette classe.
2) Définir une méthode afficher de la classe point2 qui affiche pour un objet de cette classe la
chaine (x; y) où x et y sont les valeurs des attributs x et y de l’objet.
3) Ecrire une méthode symetriquePR de la classe point2 telle que P.symetriquePR(Q) renvoie le
symétrique du point P dans la symétrie centrale de centre le point Q.
4) Ecrire une méthode appartientDroite de la classe point2 telle que P.appartientDroite(A,B)
renvoie True si lP appartient à la droite (AB) et False sinon.
3. L’héritage et la surchage de méthode
Dériver une classe. L’héritage est l’un des aspects très positif de la programmation orienté objet.
Les classes que l’on définit peuvent hériter des attributs et méthodes d’autres classes. Par défaut,
toutes les classes sont descendantes de la classe object et ainsi tous les objets que l’on crée en Python
possèdent les attributs et méthodes de cette classe. Vérifions le :
>>> issubclass (point2 , object )
>>> issubclass (list , object )
>>> issubclass (type , object )
>>> dir( object )
>>> dir( point2 )
Lorsque l’on veut que l’héritage provienne d’un classe précise, on doit le préciser dans la définition
de la nouvelle classe. Ce procédé s’appelle la dérivation de classe.
La classe dérivée possède alors les attributs et méthode de la classe dont elle dérive et ses propres
attributs et méthodes.
Dérivons par exemple la classe point2 :
COMPLÉMENTS DU COURS PYTHON - 01
5
class point2Mobile ( point2 ):
""" Cette classe hérite de la classe point2 """
t=0
v=None
def info(self):
print (" A l’instant ",self.t,"s, le mobile se trouve en ")
self. affiche ()
print (" avec une vitesse égale à :", self.v)
Dans le shell, on peut alors saisir :
>>> P= point2Mobile ()
>>> P. initialise (2 ,3)
>>> P.t=10
>>> P.v=(1 ,2)
>>> P.info ()
Surchager une méthode. Si l’on souhaite modifier une méthode de la classe parente en gardant le
même nom pour la méthode de la classe descendante, c’est possible. On dit que l’on procède à une
surcharge de méthode. Voilà ce que cela peut donner dans l’exemple précédent pour la méthode
initialise :
class point2Mobile ( point2 ):
""" Cette classe hérite de la classe point2 """
t=0
v=None
def initialise (self ,a,b,tps ,vt):
self.x,self.y,self.t,self.v=a,b,tps ,vt
Bien entendu, la méthode de la classe point2 elle reste inchangée.
La surcharge de méthode est en particulier très utile pour les méthodes spéciales de Python. En effet,
les classes Python possèdent des méthodes dont les identificateurs commencent et se terminent par
deux « underscore ».
Certaines sont associées aux opérateurs. Par exemple l’opérateur ==, qui existe dans la plupart des
classes de base de Python, est défini par la méthode __eq__ . On peut et on doit parfois surcharger
cet opérateur. Par exemple, pour la classe point2, essayer les instructions suivantes :
>>> P= point2 ();Q= point2 ()
>>> P. initialise (1 ,2);Q. initialise (1 ,2)
>>> P==Q
Surcharger la méthode __eq__ de la manière suivante :
def __eq__ (self ,Q):
return (self.x==Q.x)and(self.y==Q.y)
COMPLÉMENTS DU COURS PYTHON - 01
6
puis exécuter la cellule contenant la définition de la classe point2, puis les trois dernières instructions
du shell, dans le même ordre que la première fois.
Parmi les méthodes spéciales se trouve la méthode __init__. Cette méthode est appelée par le
constructeur de la classe lorsqu’on instancie un objet de celle-ci. En surchargeant cette méthode on
peut transmettre des paramètres au constructeur et affecter aux attributs ces paramètres. Voici une
façon de surcharger cette méthode pour la classe point2 :
def __init__ (self ,a,b):
self.x=a;self.y=b
Pour définir un objet point2, on écrira alors :
>>> P= point2 (1 , -2)
Les autres principales méthodes spéciales que l’on surcharge assez souvent :
– __str__ : qui contrôle la conversion en chaîne de caractères, utilisée de façon transparente par la
fonction print ;
– __repr__ : qui contrôle l’affichage dans le shell de l’objet ;
– les opérateurs de comparaison, soit __ne__, __le__ , __lt__ , __ge__, __gt__ ;
– les opérations, soit __add__ pour + , __sub__ pour -, __mul__ pour * , __div__ pour /, __floordiv__
pour //.
[Qu. 2]
1) Surcharger les méthodes __add__, __repr__ pour la classe point2.
2) Surcharger aussi la méthode __mul__ pour qu’elle retourne le produit scalaire des vecteurs d’origine l’origine du repère et d’extrémités les paramètres de cette méthode.
[Qu. 3] Dériver la classe list en une classe vecteur et surcharger les méthodes __init__ , __add__
et __rmul__ (multiplication à droite) pour que la somme de deux vecteurs se fasse composante par
composante et la multiplication par un nombre multiplie chaque composante du vecteur par ce
nombre.
4. Créer un module
Pour créer un module, on enregistre le fichier contenant les objets que l’on a définis et on pourra alors
ensuite importer certains de ces objets ou tous suivant le procédé que l’on utilise pour les modules
math,matplotlib, random et d’autres...
Téléchargement