Introduction au langage Python par l'exemple


précédentsommairesuivant

VI. 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.

Image non disponible

VI-A. Une classe Objet

Programme (classes_01)
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
# -*- 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
Sélectionnez
1.
2.
3.
4.
objet1=[un,100]
objet1=[un,200]
objet1=[un,0]
objet2=[un,0]

VI-B. Une classe Personne

Programme (classes_02)
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
# -*- coding=utf-8 -*-

class Personne:
    # attributs de la classe
    # non déclarés - peuvent être créés dynamiquement

    # méthode
    def identite(self):
        # a 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
Sélectionnez
1.
personne=[Paul,Langevin,48]

VI-C. La classe Personne avec un constructeur

Programme (classes_03)
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
# -*- 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):
        # a 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
Sélectionnez
1.
personne=[Paul,Langevin,48]

VI-D. La classe Personne avec contrôles de validité dans le constructeur

Programme (classes_04)
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
# -*- coding=utf-8 -*-

import re

# -------------------
# une classe d'exceptions 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
Sélectionnez
1.
2.
3.
personne=[Paul,Langevin,48]
l'age doit etre un entier positif
personne=[x,x,0]

VI-E. Ajout d'une méthode faisant office de second constructeur

Programme (classes_05)
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
# -*- coding=utf-8 -*-

import re

# -------------------
# une classe d'exceptions 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 se situe au niveau des 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
Sélectionnez
1.
2.
3.
personne=[Paul,Langevin,48]
l'age doit etre un entier positif
personne=[Paul,Langevin,48]

VI-F. Une liste d'objets Personne

Programme (classes_06)
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
# -*- 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
Sélectionnez
1.
2.
groupe[0]=[Paul,Langevin,48]
groupe[1]=[Sylvie,Lefur,70]

VI-G. Création d'une classe dérivée de la classe Personne

Programme (classes_07)
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
# -*- 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] commele montrent les résultats ci-dessous.
Résultats
Sélectionnez
1.
2.
groupe[0]=[Paul,Langevin,48,anglais]
groupe[1]=[Sylvie,Lefur,70]

VI-H. Création d'une seconde classe dérivée de la classe Personne

Programme (classes_08)
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
# -*- 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
Sélectionnez
1.
2.
3.
groupe[0]=[Paul,Langevin,48,anglais]
groupe[1]=[Sylvie,Lefur,70]
groupe[2]=[Steve,Boer,22,iup2 qualite]

précédentsommairesuivant

  

Licence Creative Commons
Le contenu de cet article est rédigé par Serge Tahé et est mis à disposition selon les termes de la Licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 3.0 non transposé.
Les logos Developpez.com, en-tête, pied de page, css, et look & feel de l'article sont Copyright © 2013 Developpez.com.