Skip to content

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

1
2
3
4
objet1=[un,100]
objet1=[un,200]
objet1=[un,0]
objet2=[un,0]

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

personne=[Paul,Langevin,48]

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

personne=[Paul,Langevin,48]

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

1
2
3
personne=[Paul,Langevin,48]
l'age doit etre un entier positif
personne=[x,x,0]

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

1
2
3
personne=[Paul,Langevin,48]
l'age doit etre un entier positif
personne=[Paul,Langevin,48]

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

groupe[0]=[Paul,Langevin,48]
groupe[1]=[Sylvie,Lefur,70]

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

groupe[0]=[Paul,Langevin,48,anglais]
groupe[1]=[Sylvie,Lefur,70]

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

groupe[0]=[Paul,Langevin,48,anglais]
groupe[1]=[Sylvie,Lefur,70]
groupe[2]=[Steve,Boer,22,iup2 qualite]