1.4. Composition d’objets¶
Nous avons jusqu’à présent considéré des objets relativement simples dont les attributs étaient des types de base de Python.
Il est l’heure de reprendre notre classe University
et de changer ses attributs nb_students
et nb_professors
pour qu’ils contiennent la liste des étudiants et des professeurs à la place de leur nombre.
Il ne s’agira donc pas de listes d’entiers ni de chaînes de caractères, mais bien d’objets de type Student
et Professor
, c’est-à-dire de nos propres classes.
Nous choisissons d’initialiser ces deux listes à l’état vide et d’ajouter les méthodes University.add_student()
et University.add_professor()
pour les peupler.
Afin de nous assurer que seuls des objets de type Student
et Professor
sont ajoutés via la méthode correspondante, nous utilisons la fonction isinstance(instance, Class)
qui indique si un objet est une instance d’une classe donnée en paramètre ou d’une de ses sous-classes.
Note
Il est important de noter que les classes filles sont considérées comme des instances de toutes leurs classes mères !
Ainsi, dans notre exemple, les instances de Bachelor
et de Master
sont des instances de Student
, de Academic
et de Human
, mais pas de Professor
.
Les classes Human
, Academic
, Professor
, Student
, Bachelor
et Master
ne sont pas modifiées par rapport à la version précédente.
Nous les incluons néanmoins dans le code ci-dessous pour que le programme soit complet et directement exécutable.
class Human:
def __init__(self, first, last):
self.first = first
self.last = last
def greet(self):
print(f"Bonjour, je suis {self.first} {self.last}.")
class Academic(Human):
def __init__(self, first, last, faculty):
Human.__init__(self, first, last)
self.faculty = faculty
def greet(self):
print(f"Bonjour, je suis {self.first} {self.last}.\n"
f"Je suis universitaire en {self.faculty}.")
class Professor(Academic):
def __init__(self, first, last, faculty, hours):
Academic.__init__(self, first, last, faculty)
self.hours = hours
def greet(self):
print(f"Bonjour, je suis {self.first} {self.last}.\n"
f"Je suis enseignant en {self.faculty}.\n"
f"Je donne {self.hours} heures de cours par semaine.")
class Student(Academic):
def __init__(self, first, last, faculty, year, average):
Academic.__init__(self, first, last, faculty)
self.year = year
self.average = average
def greet(self):
print(f"Bonjour, je suis {self.first} {self.last}.\n"
f"Je suis étudiant de bachelor en {self.faculty}.\n"
f"Ma moyenne est de {self.average}.\n"
f"Je suis actuellement en {self.year}e année.")
class Bachelor(Student):
def __init__(self, first, last, faculty, year, average):
Student.__init__(self, first, last, faculty, year, average)
def greet(self):
print(f"Bonjour, je suis {self.first} {self.last}.\n"
f"Je suis étudiant de bachelor en {self.faculty}.\n"
f"Ma moyenne est de {self.average}.\n"
f"Je suis actuellement en {self.year}e année.\n"
f"J'aurai terminé dans {3 - self.year} an(s) !")
class Master(Student):
def __init__(self, first, last, faculty, year, average):
Student.__init__(self, first, last, faculty, year, average)
def greet(self):
print(f"Bonjour, je suis {self.first} {self.last}.\n"
f"Je suis étudiant de master en {self.faculty}.\n"
f"Ma moyenne est de {self.average}.\n"
f"Je suis actuellement en {self.year}e année.\n"
f"J'aurai terminé dans {2 - self.year} an(s) !")
class University:
students = []
professors = []
def __init__(self, name, faculties):
self.name = name
self.faculties = faculties
def add_professor(self, professor):
if isinstance(professor, Professor): # on vérifie le type
self.professors.append(professor) # on l'ajoute si compatible
else: # sinon on indique l'erreur
print(f"L'objet n'est pas un professeur (type {type(professor)}).")
def add_student(self, student):
if isinstance(student, Student):
self.students.append(student)
else:
print(f"L'objet n'est pas un étudiant (type {type(student)}).")
def present(self, long=True):
# cette fois, on affiche la longueur des listes
print(f"L'université de {self.name} compte {len(self.students)} étudiants "
f"et {len(self.professors)} professeurs dans {len(self.faculties)} facultés :")
if long:
for fac in self.faculties:
print(f"- {fac}")
else:
for i in range(len(self.faculties)):
print(f"- {self.faculties[i]}")
if i == 1 and len(self.faculties) > 3:
print("- ...")
break
def present_members(self, long=True):
print("Professeurs :")
for professor in self.professors: # pour chaque professeur...
if long:
professor.greet() # on lui demande de se présenter
else: # ou on affiche son prénom et nom
print(f"- {professor.first} {professor.last}")
print("Étudiants :")
for student in self.students:
if long:
student.greet()
else:
print(f"- {student.first} {student.last}")
# on fournit les paramètres souhaités pour l'initialisation de l'instance
u_micro = University(
"Micropolis", ["Droit", "Économie", "Lettres", "Sciences"])
# on essaie d'ajouter un entier à la liste des étudiants (erreur)
u_micro.add_student(42)
# on essaie d'ajouter un étudiant à la liste des professeurs (erreur)
u_micro.add_professor(Student("Camille", "Dubois", "histoire", 1, 3.8))
# on ajoute des étudiants de bachelor
u_micro.add_student(Bachelor("Benjamin", "Legrand", "droit", 3, 5.1))
u_micro.add_student(Bachelor("Emma", "Dupont", "biologie", 2, 5.3))
# puis on ajoute des étudiants de master
u_micro.add_student(Master("Alice", "Martin", "chimie", 2, 4.3))
u_micro.add_student(Master("David", "Petit", "informatique", 1, 4.8))
# enfin on ajoute des professeurs
u_micro.add_professor(Professor("Brian", "Smith", "informatique", 7))
u_micro.add_professor(Professor("Clara", "Jones", "histoire", 6))
u_micro.present()
u_micro.present_members(False)
L'objet n'est pas un étudiant (type <class 'int'>).
L'objet n'est pas un professeur (type <class '__main__.Student'>).
L'université de Micropolis compte 4 étudiants et 2 professeurs dans 4 facultés :
- Droit
- Économie
- Lettres
- Sciences
Professeurs :
- Brian Smith
- Clara Jones
Étudiants :
- Benjamin Legrand
- Emma Dupont
- Alice Martin
- David Petit
On note que le programme affiche bien un message d’erreur lorsque l’on essaie d’ajouter un objet de mauvais type dans une liste d’étudiants ou de professeurs.
Le code de notre programme peut sembler long pour les tâches qu’il accomplit, mais il est à présent bien structuré et pourra aisément être modifié ou amélioré par la suite. Il sera également beaucoup plus facile à déboguer.