5. Les classes et objets
La classe est le moule à partir duquel sont fabriqués des objets. On dit de l'objet que c'est l'instance d'une classe.
![]() |
5.1. Une classe Objet
Programme (classes_01)
# -*- coding=utf-8 -*-
class Objet:
"""une classe Objet vide"""
# toute variable peut avoir des attributs par construction
obj1=Objet()
obj1.attr1="un"
obj1.attr2=100
# affiche l'objet
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
# modifie l'objet
obj1.attr2+=100
# affiche l'objet
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
# affecte la référence objet1 à objet2
obj2=obj1
# modifie obj2
obj2.attr2=0
# affiche les deux objets
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
print "objet2=[{0},{1}]".format(obj2.attr1,obj2.attr2)
Notes :
- ligne 4 : une autre forme de commentaire. Celui-ci précédé de trois " peut alors s'étaler sur plusieurs lignes ;
- lignes 3-4 : une classe objet vide ;
- ligne 7 : instanciation de la classe Objet ;
- ligne 17 : copie de références. Les variables obj1 et obj2 sont deux pointeurs (références) sur un même objet.
Résultats
5.2. Une classe Personne
Programme (classes_02)
# -*- coding=utf-8 -*-
class Personne:
# attributs de la classe
# non déclarés - peuvent être créés dynamiquement
# méthode
def identite(self):
# à priori, utilise des attributs inexistants
return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
# ---------------------------------- main
# les attributs sont publics et peuvent être créés dynamiquement
p=Personne()
p.prenom="Paul"
p.nom="Langevin"
p.age=48
# appel d'une méthode
print "personne={0}\n".format(p.identite())
Notes :
- lignes 3-10 : une classe avec une méthode ;
- ligne 8 : toute méthode d'une classe doit avoir pour premier paramètre, l'objet self qui désigne l'objet courant.
Résultats
5.3. La classe Personne avec un constructeur
Programme (classes_03)
# -*- coding=utf-8 -*-
class Personne:
# constructeur
def __init__(self,prenom,nom,age):
self.prenom=prenom;
self.nom=nom;
self.age=age;
# méthode
def identite(self):
# à priori, utilise des attributs inexistants
return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
# ---------------------------------- main
# un objet Personne
p=Personne("Paul","Langevin",48)
# appel d'une méthode
print "personne={0}\n".format(p.identite())
Notes :
- ligne 6 : le constructeur d'une classe s'appelle __init__. Comme pour les autres méthodes, son premier paramètre est self ;
- ligne 18 : un objet Personne est construit avec le constructeur de la classe.
Résultats
5.4. La classe Personne avec contrôles de validité dans le constructeur
Programme (classes_04)
# -*- coding=utf-8 -*-
import re
# -------------------
# une classe d'exception propriétaire
class MyError(Exception):
pass
class Personne:
# constructeur
def __init__(self,prenom="x",nom="x",age=0):
# le prénom doit être non vide
match=re.match(r"^\s*(\S+)\s*$",prenom)
if not match:
raise MyError("Le prenom ne peut etre vide")
else:
self.prenom=match.groups()[0]
# le nom doit être non vide
match=re.match(r"^\s*(\S+)\s*$",nom)
if not match:
raise MyError("Le nom ne peut etre vide")
else:
self.nom=match.groups()[0]
# l'âge doit être valide
match=re.match(r"^\s*(\d+)\s*$",str(age))
if not match:
raise MyError("l'age doit etre un entier positif")
else:
self.age=match.groups()[0]
def __str__(self):
return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
# ---------------------------------- main
# un objet Personne
try:
p=Personne(" Paul "," Langevin ",48)
print "personne={0}".format(p)
except MyError, erreur:
print erreur
# un autre objet Personne
try:
p=Personne(" xx "," yy "," zz")
print "personne={0}".format(p)
except MyError, erreur:
print erreur
# une autre personne
try:
p=Personne()
print "personne={0}".format(p)
except MyError, erreur:
print erreur
Notes :
- lignes 7-8 : une classe MyError dérivée de la classe Exception. Elle n'ajoute aucune fonctionnalité à cette dernière. Elle n'est là que pour avoir une exception propriétaire ;
- ligne 13 : le constructeur a des valeurs par défaut pour ses paramètres. Ainsi l'opération p=Personne() est équivalente à p=Personne("x","x",0) ;
- lignes 15-9 : on analyse le paramètre prenom. Il doit être non vide. Si ce n'est pas le cas, on lance l'exception MyError avec un message d'erreur ;
- lignes 21-25 : idem pour le nom ;
- lignes 27-31 : vérification de l'âge ;
- lignes 33-34 : la fonction __str__ remplace la méthode qui s'appelait identite précédemment ;
- lignes 38-42 : instanciation d'une personne puis affichage de son identité ;
- ligne 39 : instanciation ;
- ligne 40 : affichage. L'opération demande d'afficher la personne p sous la forme d'une chaîne de caractères. L'interpréteur Python appelle alors automatiquement la méthode p.__str__() si elle existe. Cette méthode joue le même rôle que la méthode toString() en Java ou dans les langages .NET ;
- lignes 41-42 : gestion d'une éventuelle exception de type MyError. Affiche alors le message d'erreur associé à l'exception ;
- lignes 44-48 : idem pour une deuxième personne instanciée avec des paramètres erronés ;
- lignes 50-54 : idem pour une troisième personne instanciée avec les paramètres par défaut.
Résultats
5.5. Ajout d'une méthode faisant office de second constructeur
Programme (classes_05)
# -*- coding=utf-8 -*-
import re
# -------------------
# une classe d'exception propriétaire
class MyError(Exception):
pass
class Personne:
# attributs de la classe
# non déclarés - peuvent être créés dynamiquement
# constructeur
def __init__(self,prenom="x",nom="x",age=0):
# le prénom doit être non vide
match=re.match(r"^\s*(\S+)\s*$",prenom)
if not match:
raise MyError("Le prenom ne peut etre vide")
else:
self.prenom=match.groups()[0]
# le nom doit être non vide
match=re.match(r"^\s*(\S+)\s*$",nom)
if not match:
raise MyError("Le nom ne peut etre vide")
else:
self.nom=match.groups()[0]
# l'âge doit être valide
match=re.match(r"^\s*(\d+)\s*$",str(age))
if not match:
raise MyError("l'age doit etre un entier positif")
else:
self.age=match.groups()[0]
def initWithPersonne(self,p):
# initialise l'objet courant avec une personne p
self.__init__(p.prenom,p.nom,p.age)
def __str__(self):
return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
# ---------------------------------- main
# un objet Personne
try:
p0=Personne(" Paul "," Langevin ",48)
print "personne={0}".format(p0)
except MyError, erreur:
print erreur
# un autre objet Personne
try:
p1=Personne(" xx "," yy "," zz")
print "personne={0}".format(p1)
except MyError, erreur:
print erreur
# une autre personne
p2=Personne()
try:
p2.initWithPersonne(p0)
print "personne={0}".format(p2)
except MyError, erreur:
print erreur
Notes :
- la différence avec le script précédent est en lignes 35-37. On a rajouté la méthode initWithPersonne. Celle-ci fait appel au constructeur __init__. Il n'y a pas possibilité d'avoir, comme dans les langages typés, des méthodes de même nom différenciées par la nature de leurs paramètres ou de leur résultat. Il n'y a donc pas possibilité d'avoir plusieurs constructeurs qui construiraient l'objet à partir de paramètres différents, ici un objet de type Personne.
Résultats
5.6. Une liste d'objets Personne
Programme (classes_06)
# -*- coding=utf-8 -*-
class Personne:
...
# ---------------------------------- main
# création d'une liste d'objets personne
groupe=[Personne("Paul","Langevin",48), Personne("Sylvie","Lefur",70)]
# identité de ces personnes
for i in range(len(groupe)):
print "groupe[{0}]={1}".format(i,groupe[i])
Notes :
- lignes 3-5 : la classe Personne déjà décrite
Résultats
5.7. Création d'une classe dérivée de la classe Personne
Programme (classes_07)
# -*- coding=utf-8 -*-
import re
class Personne:
...
class Enseignant(Personne):
def __init__(self,prenom="x",nom="x",age=0,discipline="x"):
Personne.__init__(self,prenom,nom,age)
self.discipline=discipline
def __str__(self):
return "[{0},{1},{2},{3}]".format(self.prenom,self.nom,self.age,self.discipline)
# ---------------------------------- main
# création d'une liste d'objets Personne et dérivés
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70)]
# identité de ces personnes
for i in range(len(groupe)):
print "groupe[{0}]={1}".format(i,groupe[i])
Notes :
- lignes 5-6 : la classe Personne déjà définie ;
- ligne 8 : déclare la classe Enseignant comme étant une classe dérivée de la classe Personne ;
- ligne 10 : le constructeur de la classe dérivée Enseignant doit appeler le constructeur de la classe parent Personne ;
- lignes 21-22 : pour afficher groupe[i], l'interpréteur utilise la méthode groupe[i].__str__(). La méthode __str__() utilisée est celle de la classe réelle de groupe[i] comme le montrent les résultats ci-dessous.
Résultats
5.8. Création d'une seconde classe dérivée de la classe Personne
Programme (classes_08)
# -*- coding=utf-8 -*-
import re
class Personne:
...
class Enseignant(Personne):
...
class Etudiant(Personne):
def __init__(self,prenom="x",nom="x",age=0,formation="x"):
Personne.__init__(self,prenom,nom,age)
self.formation=formation
def __str__(self):
return "[{0},{1},{2},{3}]".format(self.prenom,self.nom,self.age,self.formation)
# ---------------------------------- main
# création d'une liste d'objets Personne et dérivés
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70), Etudiant("Steve","Boer",22,"iup2 qualite")]
# identité de ces personnes
for i in range(len(groupe)):
print "groupe[{0}]={1}".format(i,groupe[i])
Notes :
- ce script est analogue au précédent.
Résultats
