Programmation orientée objet

publicité
Python
Programmation orientée objet
Suite sur les fichiers
La première ligne de cet exemple importe l'intégralité du module os,
lequel contient de nombreuses fonctions intéressantes pour l'accès
au système d'exploitation. La seconde ligne utilise la fonction
getcwd() du module os Comme vous pouvez le constater, la fonction
getcwd() renvoie le nom du répertoire courant (getcwd = get current
working directory).
>>> import os
>>> rep_cour = os.getcwd()
>>> print rep_cour
'/home/housni'
Suite sur les fichiers
Si vous souhaiterez forcer Python à changer son répertoire
courant, afin que celui-ci corresponde à vos attentes. Pour ce
faire, utilisez les commandes suivantes en début de session.
(Nous supposons ici que le répertoire visé est le répertoire
/home/exercices . Vous pouvez utiliser cette syntaxe (c'est-àdire des caractères / et non \ en guise de séparateurs : c'est la
convention en vigueur dans le monde Unix). Python effectuera
automatiquement les conversions nécessaires, suivant que
vous travaillez sous MacOS, Linux, ou Windows.
>>> from os import chdir
>>> chdir("/home/exercices")
Introduction à la programmation orientée objet
Dans ce chapitre, nous allons créer nos premières
classes, nos premiers attributs et nos premières
méthodes. Nous allons aussi essayer de
comprendre les mécanismes de la programmation
orientée objet en Python.
Python offre la possibilité de programmer en
Orienté objet. Le mécanisme de classe en Python
est un mélange des mécanismes de classes de
C++ et de Modula-3.
La synthaxe…
La forme la plus simple de définition de classe ressemble à ceci :
class Nomclasse:
<instruction1>
…
<instructionN>
Dans la pratique, les instructions à l’intérieur de la définition de classe seront
souvent des définitions de fonctions, mais d’autres instructions sont
acceptées.
L’objet classe permet deux types d’opération : La référenciation des attributs
et l’instanciation.
La référence d’attributs : Nomclasse.i où i est un attribut de Nomclasse est
une références d’attribut valide.
L’instanciation(création d’une instance (objet) Nomclasse):
x=Nomclasse() affecte la nouvelle instance à la variable x
A l’intérieur de la classe…
On trouve deux types d’attributs :
-
données (idem que les données membre en C)
-
Les méthodes (idem que fonction membre en C)
1)
Les données
Les données n’ont pas besoin d’être déclarée; Comme les
variable locale, elles apparaissent lorsqu’on leur affecte une
valeur la première fois.
ex : class MaClasse :
def f(x):
print « hello World »
i=123456
x= MaClasse()
x.compteur = 1 #creation de l’attribut compteur
Attribut d'instance vs. de classe
Class NomClasse(object):
"Description de la classe"
attc1,...,attcC=val1,...,valC
def __init__(self,p1,p2,....,pP):
self.atti1=f(p1,p2,...pP)
....
self.attiN=f(p1,p2,...pP)
def meth1(self,...):
...
...
def methM(self,...):
...
Les attc sont des attributs de
classe : toute instance de la
classe peut y accéder. S'ils
sont modifiés par un objet, ils
sont modifiés pour les autres
instances (soulignés en UML).
Les atti sont des attributs
d'instance, ils sont propres à l'objet, créés et détruits avec
lui.
Exemple
class exemple:
var1=12
def __init__(self,v):
self.var1=v
def afficheAttClasse(self):
print(exemple.var1)
def afficheAttInstance(self):
print(self.var1)
def plus1(self):
exemple.var1+=1
x=exemple(33)
y=exemple(44)
x.afficheAttInstance()
x.afficheAttClasse()
y.plus1()
x.afficheAttInstance()
x.afficheAttClasse()
A l’intérieur de la classe…
2) Les méthodes
Une méthode est appelée comme en C++ :
x.f()
Vous avez surement remarqué que la fonction f définie dans MaClasse a
été appelée sans paramètre alors que la définition en contenait un. Ca
devrait normalement déclencher une exception. Mais il n’en est rien car la
particularité des méthodes est que l’objet est passé comme premier
argument de la fonction. Le plus souvent par convention appelé « self »
pour amélioré la lisibilité du programme .
L’appel x.f() est donc équivalent à MaClasse.f(x).
Il n’est pas nécessaire que la définition de la méthode soit
comprise dans la définition de la classe.
Ex : def f1 (self,x,y):
return min(x,x+y)
class C:
f=f1
La visibilité en Python
● Pas de propriétés privées ou protégées
● Mais simulation de private : variables « brouillées »
– Un attribut d'une instance o d'une classe C est brouillé si son nom est
définit dans C avec la forme : __nom
– Il est renommé automatiquement à la création de l'instance o et n'est
donc plus accessible « hors » de C sans connaître le mécanisme
précis !
– En fait il est renommé _C__nom et est accessible sous cette forme
comme tous les attributs de o (car stocké ainsi dans le dictionnaire
o.__dict__)
– Contourner l'impossibilité d'accès direct à une variable brouillée n'a
pas de sens et est fortement déconseillé !
Méthodes prédéfinies…
Python contient une liste de méthodes dites spéciales :
En particulier, la méthode __init__(self)…
Lorsqu’une classe définit la méthode spéciale __init__(), l’instantation de la
classe appelle automatiquement cette méthode.
Il s’agit en fait de ce qu’on appel en C++ un constructeur.
Bien sûr, la méthode __init__() peut prendre autant de paramètre qu’on le
vaut, pour une flexibilité accrue…
Ex : class Complexe:
def __init__(self, partiereelle, partieimaginaire):
self.r = partiereelle
self.i = partieimaginaire
x = Complexe(3.0,-4.5)
x.r, x.i donne: (3.0, -4.5)
L’héritage



Il est possible de définir une classe spécialisée à partir d'une
autre classe plus générale (dite classe de base ou classe mère
ou super-classe)
La nouvelle classe (dite dérivée) permet à un objet qui l'instancie
d'hériter des caractéristiques (attributs et méthodes) décrites par
la classe héritée
La classe dérivée peut ensuite subir des modifications :

Définition de nouveaux attributs et de nouvelles méthodes

Redéfinition de méthodes de la classe de base

Extension de méthodes de la classe de base
L’héritage
Lorsqu'une classe hérite d'une autre elle peut :

Utiliser les attributs de la classe parent

Utiliser les méthodes de la classe parent

définir de nouveaux attributs

définir de nouvelle méthodes

Redéfinir certaines méthodes
L’héritage
Lorsqu'une classe hérite d'une autre elle peut :

Utiliser les attributs de la classe parent

Utiliser les méthodes de la classe parent

définir de nouveaux attributs

définir de nouvelle méthodes

Redéfinir certaines méthodes
Relation entre classe mère et fille
● L'héritage dénote une relation de généralisation /
spécialisation
● Toute relation d'héritage peut se traduire par la phrase : «
La classe dérivée est une version spécialisée de la classe
de base »
● Le principe de généralisation/spécialisation invoque donc
une relation dite relation est-un
Avantages de l'héritage
● Factorisation de comportements communs à une hiérarchie : code de
taille plus faible
● Lors d'une dérivation, seul le code spécifique reste à écrire :
développement plus rapide
● Modélisation d'une notion très naturelle : systèmes conceptuellement
bien conçus
● Permet le principe du polymorphisme fort
● Plus une classe est haute dans la hiérarchie plus son code est
sollicité donc débogué rapidement
● Si la hiérarchie est bien pensée : permet une programmation
différentielle
Exemple
class Voiture:
roues = 4
moteur = 1
def __init__(self):
self.nom = "A déterminer"
def allumer(self):
print "La voiture démarre"
class VoitureSport(Voiture):
def __init__(self):
self.nom = "Ferrari"
>>> ma_voiture=Voiture()
>>> ma_voiture.nom
'A déterminer'
>>> ma_voiture.roues
4
>>> ma_voiture_sport=VoitureSport()
>>> ma_voiture_sport.nom
'Ferrari'
>>> ma_voiture_sport.roues
4
>>> ma_voiture_sport.allumer()
La voiture démarre
Polymorphisme / surcharge de méthode
class Voiture:
roues = 4
moteur = 1
def __init__(self):
self.nom = "A déterminer"
def allumer(self):
print "La voiture démarre"
class VoitureSport(Voiture):
def __init__(self):
self.nom = "Ferrari"
def allumer(self):
print "La voiture de sport démarre"
>>> ma_voiture=Voiture()
>>> ma_voiture.nom
'A déterminer'
>>> ma_voiture.roues
4
>>> ma_voiture_sport=VoitureSport()
>>> ma_voiture_sport.nom
'Ferrari'
>>> ma_voiture_sport.roues
4
>>> ma_voiture_sport.allumer()
La voiture de sport démarre
Polymorphisme / surcharge de méthode
il est possible d'appeler la méthode du parent puis de faire la spécificité de la méthode. On peut d'ailleurs
appeler n'importe quelle autre méthode.
class Voiture:
roues = 4
moteur = 1
def __init__(self):
self.nom = "A déterminer"
def allumer(self):
print "La voiture démarre"
class VoitureSport(Voiture):
def __init__(self):
self.nom = "Ferrari"
def allumer(self):
Voiture.allumer(self)
print "La voiture de sport démarre"
ma_voiture_sport = VoitureSport()
ma_voiture_sport.allumer()
La voiture démarre
La voiture de sport démarre
L’héritage
La syntaxe pour définir une classe dérive est la suivante :
Class Nomclassedérivée (NomClassedeBase):
<instruction1>
…
<instructionN>
Remarque : A la place d’un nom de classe de base, une expression
est acceptée. Ce qui est utile lorsque le définition de la classe de
base se trouve dans un autre module..
Ex : class NomClasseDerivee(nommod.NomClasseDeBase):
L’exécution d’une définition de classe dérivée se déroule
comme une classe de base. Quand l’objet classe est construit, la
classe de base est mémorisée.C’est ce qui permet de trouver
facilement un attribut. Lorsqu’un attributs est référence, il est
recherché dans la classe dérivée s’il ne s’y trouve pas on le
recherchera dans la classe de base.
L’héritage multiple
Python supporte également l’héritage multiple.
Une définition de classe avec plusieurs classes de base ressemble à
:
Class NomClasseDerivee (Base1,Base2,..,BaseN)
<instruction1>
…
<instructionN>
Lorsqu’on référence un attribut, la recherche s’effectue en
profondeur càd de gauche à droite? Donc si un attribut n’est pas
trouvé dans ClasseDerivee, on le cherchera d’abord dans base1,
puis dans base2, et ainsi de suite jusqu’à ce qu’on le trouve…
Rem : Il faut faire attention aux conflits accidentelles!!
Par exemple, si on crée une classe dérivée de deux autres
classes dérivées de la même classe de base…risque de
problèmes!!!!
Téléchargement