Python : Programmation orientée objet

19 juillet 2014 rdorigny 0 commentaires

Comme tout langage digne de ce nom, Python propose évidemment une programmation orientée objet. D'ailleurs, on retrouve la POO un peut partout dans les librairies du framework de base.

Je ne reviendrais pas sur les bases de ce type de programmation, considérant que ces notions sont connus du lecteur. En revanche, je vous donnerai quelques exemples pour vous montrer comment la POO est implémentée sous Python.





Ce chapitre est un fork de la documentation fournie par Gérard Swinnen sur le site développez.com . Elle est très complète et détaillée, aussi j'ai jugé intéressant de la résumer pour ceux qui comme moi, se rebute à la lecture d'une documentation de plus de 300 pages. Ceci dit, si vous souhaitez aller plus loin, n'hésiter à la récupérer au format pdf.


1)Les classes

Voici un exemple, on notera les attributs définis dans le constructeur. N'oubliez de mettre l'indentation:
class Rectangle: "ceci est la classe Rectangle" # initialisation d'un objet # définition des attributs avec des valeurs par défaut def __init__(self, long = 0.0, larg = 0.0, coul = "blanc"): self.longueur = long self.largeur = larg self.couleur = coul # définition de la méthode qui calcule la surface def calculSurface(self): print "surface = %.2f m2" %(self.longueur * self.largeur) # définition de la méthode qui transforme un rectangle en carré def changeCarre(self, cote): self.longueur = cote self.largeur = cote

Et pour l'utilisation:
# création d'un objet Rectangle avec les paramètres par défaut rect1 = Rectangle() print rect1.longueur, rect1.largeur, rect1.couleur # sans surprise : rect1.calculSurface() # on change le rectangle en carré rect1.changeCarre(30) rect1.calculSurface() # création d'un objet Rectangle avec des paramètres imposés rect2 = Rectangle(2, 3, "rouge") rect2.calculSurface()

2)Héritage et polymorphisme

Voici un exemple d'héritage:
>>> class Mammifere(object): ... caract1 = "il allaite ses petits ;" >>> class Carnivore(Mammifere): ... caract2 = "il se nourrit de la chair de ses proies ;" >>> class Chien(Carnivore): ... caract3 = "son cri s'appelle aboiement ;" >>> mirza = Chien() >>> print(mirza.caract1, mirza.caract2, mirza.caract3) il allaite ses petits ; il se nourrit de la chair de ses proies ;son cri s'appelle aboiement ;

Un autre exemple qui va nous permettre d'expliquer le polymorphisme:
class Atome: """atomes simplifiés, choisis parmi les 10 premiers éléments du TP""" table =[None, ('hydrogène',0),('hélium',2),('lithium',4), ('béryllium',5),('bore',6),('carbone',6),('azote',7), ('oxygène',8),('fluor',10),('néon',10)] def __init__(self, nat): "le n° atomique détermine le n. de protons, d'électrons et de neutrons" self.np, self.ne = nat, nat # nat = numéro atomique self.nn = Atome.table[nat][1] def affiche(self): print() print("Nom de l'élément :", Atome.table[self.np][0]) print("%s protons, %s électrons, %s neutrons" % (self.np, self.ne, self.nn)) class Ion(Atome): """les ions sont des atomes qui ont gagné ou perdu des électrons""" def __init__(self, nat, charge): "le n° atomique et la charge électrique déterminent l'ion" Atome.__init__(self, nat) self.ne = self.ne - charge self.charge = charge def affiche(self): Atome.affiche(self) print("Particule électrisée. Charge =", self.charge) ### Programme principal : ### a1 = Atome(5) a2 = Ion(3, 1) a3 = Ion(8, -2) a1.affiche() a2.affiche() a3.affiche()

Ce qui affichera
Nom de l'élément : bore 5 protons, 5 électrons, 6 neutrons Nom de l'élément : lithium 3 protons, 2 électrons, 4 neutrons Particule électrisée. Charge = 1 Nom de l'élément : oxygène 8 protons, 10 électrons, 8 neutrons Particule électrisée. Charge = -2

Le script reproduit à la page suivante génère des objets Atome() et des objets Ion(). Dans notre programmation, la classe qui définit les objets Ion() sera donc une classe dérivée de la classe Atome() : elle héritera d'elle tous ses attributs et toutes ses méthodes, en y ajoutant les siennes propres.
L'une de ces méthodes ajoutées (la méthode affiche()) remplace une méthode de même nom héritée de la classe Atome(). Les classes Atome() et Ion() possèdent donc chacune une méthode de même nom, mais qui effectuent un travail différent. On parle dans ce cas de polymorphisme. On pourra dire également que la méthode affiche() de la classe Atome() a été surchargée.

3)Module de classe

Voyons comment on réalise un module de classe. Voici un exemple:
class Rectangle(object): "Classe de rectangles" def __init__(self, longueur =0, largeur =0): self.L = longueur self.l = largeur self.nom ="rectangle" def perimetre(self): return "(%d + %d) * 2 = %d" % (self.L, self.l,(self.L + self.l)*2) def surface(self): return "%d * %d = %d" % (self.L, self.l, self.L*self.l) def mesures(self): print("Un %s de %d sur %d" % (self.nom, self.L, self.l)) print("a une surface de %s" % (self.surface(),)) print("et un périmètre de %sn" % (self.perimetre(),)) class Carre(Rectangle): "Classe de carrés" def __init__(self, cote): Rectangle.__init__(self, cote, cote) self.nom ="carré" if __name__ == "__main__": r1 = Rectangle(15, 30) r1.mesures() c1 = Carre(13) c1.mesures()

Donc pour l'utiliser:
>>> import formes >>> f1 = formes.Rectangle(27, 12) >>> f1.mesures() Un rectangle de 27 sur 12 a une surface de 27 * 12 = 324 et un périmètre de (27 + 12) * 2 = 78 >>> f2 = formes.Carre(13) >>> f2.mesures() Un carré de 13 sur 13 a une surface de 13 * 13 = 169 et un périmètre de (13 + 13) * 2 = 52

On voit dans ce script que la classe Carre() est construite par dérivation à partir de la classe Rectangle() dont elle hérite toutes les caractéristiques. En d'autres termes, la classe Carre() est une classe fille de la classe Rectangle(). Vous pouvez remarquer encore une fois que le constructeur de la classe Carre() doit faire appel au constructeur de sa classe parente (rectangle.__init__(self, ...) ), en lui transmettant la référence de l'instance (self) comme premier argument.

Quant à l'instruction :
if __name__ == "__main__":

placée à la fin du module, elle sert à déterminer si le module est « lancé » en tant que programme autonome (auquel cas les instructions qui suivent doivent être exécutées), ou au contraire utilisé comme une bibliothèque de classes importée ailleurs. Dans ce cas cette partie du code est sans effet.

Conclusion

Voila pour ce chapitre qui est assez succinct mais qui reprend l'essentiel de ce qu'il faut connaitre.







Pseudonyme (obligatoire) :
Adresse mail (obligatoire) :
Site web :




© 2017 www.doritique.fr par Robert DORIGNY