Salut à toi, futur expert en développement ! Aujourd'hui, on s'attaque à un pilier fondamental de la programmation moderne : la Programmation Orientée Objet (POO) en Python. Que tu sois en licence d'informatique ou simplement désireux d'améliorer tes compétences, cette série d'exercices progressifs est faite pour toi. Prépare-toi à manipuler des classes, des objets, de l'héritage et bien plus encore !
Compétences travaillées :
- Création et manipulation de classes et d'objets.
- Compréhension des attributs et des méthodes.
- Application des principes d'encapsulation, d'héritage et de polymorphisme.
- Utilisation des méthodes spéciales (dunder methods).
- Développement d'une logique de conception orientée objet robuste.
Erreurs fréquentes :
- Confondre une classe et une instance (objet). Une classe est le plan, un objet est la réalisation.
- Oublier le paramètre
selfdans les méthodes d'instance. Il représente l'instance elle-même. - Mal gérer la visibilité des attributs (privés/publics).
- Ne pas comprendre quand utiliser l'héritage versus la composition.
- Ignorer les exceptions : un bon code POO doit être robuste face aux erreurs.
Exercices de Programmation Orientée Objet en Python
Exercice 1 : Création d'une Classe Basique
Tu es chargé de créer un système simple pour gérer les livres d'une bibliothèque.
a) Crée une classe nommée Livre. Cette classe doit avoir un constructeur __init__ qui prend en paramètres le titre, l'auteur et l'année_publication du livre. Ces paramètres devront être stockés comme attributs de l'objet.
b) Instancie deux objets de type Livre :
- "Le Seigneur des Anneaux", J.R.R. Tolkien, 1954
- "1984", George Orwell, 1949
c) Affiche le titre et l'auteur de chaque livre instancié.
Barème indicatif : 2 points
Correction :
a) La création de la classe Livre avec son constructeur est la première étape. Le constructeur (__init__) est une méthode spéciale appelée lors de la création d'un nouvel objet. Le paramètre self est toujours le premier argument et représente l'instance de l'objet.
class Livre:
def __init__(self, titre, auteur, annee_publication):
self.titre = titre
self.auteur = auteur
self.annee_publication = annee_publication
b) Pour instancier des objets, tu dois appeler le nom de la classe comme une fonction, en lui passant les arguments nécessaires au constructeur.
livre1 = Livre("Le Seigneur des Anneaux", "J.R.R. Tolkien", 1954)
livre2 = Livre("1984", "George Orwell", 1949)
c) Pour accéder aux attributs d'un objet, tu utilises la notation pointée (objet.attribut).
print(f"Livre 1 : {livre1.titre} de {livre1.auteur}")
print(f"Livre 2 : {livre2.titre} de {livre2.auteur}")
Résultat :
Livre 1 : Le Seigneur des Anneaux de J.R.R. Tolkien
Livre 2 : 1984 de George Orwell
Astuce : Le __init__ est l'équivalent du constructeur dans d'autres langages. Il est crucial pour initialiser l'état de ton objet.
Exercice 2 : Ajout de Méthodes
Reprends ta classe Livre. Ajoute une méthode nommée afficher_details qui affichera tous les détails du livre (titre, auteur, année de publication) dans une phrase formatée.
a) Modifie la classe Livre pour inclure cette méthode.
b) Appelle cette méthode pour les deux livres instanciés précédemment.
Barème indicatif : 2 points
Correction :
a) Une méthode est une fonction définie à l'intérieur d'une classe. Elle prend toujours self comme premier argument pour pouvoir accéder aux attributs de l'instance.
class Livre:
def __init__(self, titre, auteur, annee_publication):
self.titre = titre
self.auteur = auteur
self.annee_publication = annee_publication
def afficher_details(self):
print(f"'{self.titre}' par {self.auteur}, publié en {self.annee_publication}.")
b) Pour appeler une méthode, tu utilises la notation pointée sur l'objet (objet.methode()).
livre1 = Livre("Le Seigneur des Anneaux", "J.R.R. Tolkien", 1954)
livre2 = Livre("1984", "George Orwell", 1949)
livre1.afficher_details()
livre2.afficher_details()
Résultat :
'Le Seigneur des Anneaux' par J.R.R. Tolkien, publié en 1954.
'1984' par George Orwell, publié en 1949.
Point méthode : Les méthodes te permettent de définir des comportements spécifiques aux objets de ta classe.
Exercice 3 : Attributs Modifiables
Ajoute un attribut disponible à ta classe Livre, initialisé à True par défaut. Crée ensuite deux méthodes : emprunter() qui met disponible à False si le livre l'est, et rendre() qui le met à True.
a) Modifie le constructeur et ajoute les méthodes emprunter et rendre à la classe Livre.
b) Crée un livre, puis simule un emprunt et un retour, en affichant l'état de disponibilité à chaque étape.
Barème indicatif : 2 points
Correction :
a) L'attribut disponible est ajouté au constructeur avec une valeur par défaut. Les méthodes vérifient l'état avant de le modifier.
class Livre:
def __init__(self, titre, auteur, annee_publication, disponible=True):
self.titre = titre
self.auteur = auteur
self.annee_publication = annee_publication
self.disponible = disponible # Nouvel attribut
def afficher_details(self):
etat = "disponible" if self.disponible else "emprunté"
print(f"'{self.titre}' par {self.auteur}, publié en {self.annee_publication}. État : {etat}.")
def emprunter(self):
if self.disponible:
self.disponible = False
print(f"Le livre '{self.titre}' a été emprunté.")
else:
print(f"Le livre '{self.titre}' n'est pas disponible pour l'emprunt.")
def rendre(self):
if not self.disponible:
self.disponible = True
print(f"Le livre '{self.titre}' a été rendu.")
else:
print(f"Le livre '{self.titre}' était déjà disponible.")
b) On instancie un livre et on appelle les méthodes pour simuler les actions.
mon_livre = Livre("Le Guide du voyageur galactique", "Douglas Adams", 1979)
mon_livre.afficher_details()
mon_livre.emprunter()
mon_livre.afficher_details()
mon_livre.rendre()
mon_livre.afficher_details()
mon_livre.rendre() # Tentative de rendre un livre déjà disponible
Résultat :
'Le Guide du voyageur galactique' par Douglas Adams, publié en 1979. État : disponible.
Le livre 'Le Guide du voyageur galactique' a été emprunté.
'Le Guide du voyageur galactique' par Douglas Adams, publié en 1979. État : emprunté.
Le livre 'Le Guide du voyageur galactique' a été rendu.
'Le Guide du voyageur galactique' par Douglas Adams, publié en 1979. État : disponible.
Le livre 'Le Guide du voyageur galactique' était déjà disponible.
Astuce : Les attributs peuvent être modifiés directement, mais encapsuler leur modification via des méthodes (emprunter, rendre) est une bonne pratique POO pour ajouter de la logique et des vérifications.
Exercice 4 : Encapsulation (Propriétés)
Il est important que l'année de publication d'un livre ne soit pas antérieure à 0 et pas postérieure à l'année actuelle. Utilise des propriétés (@property et @annee_publication.setter) pour gérer l'accès et la modification de l'attribut annee_publication de ta classe Livre.
a) Modifie la classe Livre pour implémenter une propriété pour annee_publication avec les validations nécessaires.
b) Teste la création d'un livre avec une année invalide (ex: -100) et la modification d'un livre avec une année future (ex: 2050).
Barème indicatif : 3 points
Correction :
a) Les propriétés permettent de contrôler l'accès aux attributs comme s'ils étaient des attributs directs, tout en exécutant du code (validations, traitements) en arrière-plan. On utilise un attribut interne (souvent préfixé par _) pour stocker la valeur réelle.
import datetime
class Livre:
def __init__(self, titre, auteur, annee_publication, disponible=True):
self.titre = titre
self.auteur = auteur
self.disponible = disponible
self.annee_publication = annee_publication # Utilise le setter ici
@property
def annee_publication(self):
return self._annee_publication
@annee_publication.setter
def annee_publication(self, value):
annee_actuelle = datetime.date.today().year
if not isinstance(value, int) or value <= 0 or value > annee_actuelle:
print(f"Attention : L'année de publication '{value}' est invalide. Elle doit être un entier positif et non future. La valeur ne sera pas modifiée.")
# Optionnel : lever une exception ValueError("Année de publication invalide")
# Pour cet exercice, nous allons juste afficher un message et ne pas changer la valeur
if not hasattr(self, '_annee_publication'): # S'assure que l'attribut existe pour la première assignation
self._annee_publication = annee_actuelle # Initialise avec une valeur par défaut valide
else:
self._annee_publication = value
def afficher_details(self):
etat = "disponible" if self.disponible else "emprunté"
print(f"'{self.titre}' par {self.auteur}, publié en {self.annee_publication}. État : {etat}.")
b) Test de la propriété avec des valeurs invalides.
# Test de création avec une année invalide
livre_test1 = Livre("Titre Test 1", "Auteur Test", -100)
livre_test1.afficher_details() # Devrait montrer l'année par défaut ou un message d'erreur lors de la création
print("-" * 20)
# Test de modification avec une année future
livre_test2 = Livre("Titre Test 2", "Autre Auteur", 2000)
livre_test2.afficher_details()
livre_test2.annee_publication = 2050 # Essai d'assigner une année future
livre_test2.afficher_details() # Devrait montrer l'année inchangée et un message d'erreur
livre_test2.annee_publication = 2010 # Essai d'assigner une année valide
livre_test2.afficher_details()
Résultat :
Attention : L'année de publication '-100' est invalide. Elle doit être un entier positif et non future. La valeur ne sera pas modifiée.
'Titre Test 1' par Auteur Test, publié aujourd'hui. État : disponible.
--------------------
'Titre Test 2' par Autre Auteur, publié en 2000. État : disponible.
Attention : L'année de publication '2050' est invalide. Elle doit être un entier positif et non future. La valeur ne sera pas modifiée.
'Titre Test 2' par Autre Auteur, publié en 2000. État : disponible.
'Titre Test 2' par Autre Auteur, publié en 2010. État : disponible.
Point méthode : L'encapsulation via @property est une manière élégante de protéger tes attributs et d'ajouter de la logique de validation sans casser l'interface de ta classe.
Exercice 5 : Héritage Simple
Tu dois maintenant gérer des livres numériques (e-books) qui ont une taille de fichier en Mo. Crée une classe LivreNumerique qui hérite de Livre et ajoute un attribut taille_mo. Assure-toi que le constructeur gère les attributs de la classe parente et le nouvel attribut.
a) Crée la classe LivreNumerique héritant de Livre. Le constructeur doit appeler le constructeur de la classe parente et initialiser taille_mo.
b) Redéfinis la méthode afficher_details dans LivreNumerique pour inclure la taille du fichier.
c) Instancie un LivreNumerique et affiche ses détails.
Barème indicatif : 3 points
Correction :
a) L'héritage permet à une classe (enfant) de réutiliser les attributs et méthodes d'une autre classe (parente). super().__init__() est utilisé pour appeler le constructeur de la classe parente.
import datetime
class Livre:
def __init__(self, titre, auteur, annee_publication, disponible=True):
self.titre = titre
self.auteur = auteur
self.disponible = disponible
self.annee_publication = annee_publication # Utilise le setter
@property
def annee_publication(self):
return self._annee_publication
@annee_publication.setter
def annee_publication(self, value):
annee_actuelle = datetime.date.today().year
if not isinstance(value, int) or value <= 0 or value > annee_actuelle:
if not hasattr(self, '_annee_publication'):
self._annee_publication = annee_actuelle # Initialise avec une valeur par défaut valide
print(f"Attention : L'année de publication '{value}' est invalide. Elle doit être un entier positif et non future. La valeur ne sera pas modifiée.")
else:
self._annee_publication = value
def afficher_details(self):
etat = "disponible" if self.disponible else "emprunté"
print(f"'{self.titre}' par {self.auteur}, publié en {self.annee_publication}. État : {etat}.")
def emprunter(self):
if self.disponible:
self.disponible = False
print(f"Le livre '{self.titre}' a été emprunté.")
else:
print(f"Le livre '{self.titre}' n'est pas disponible pour l'emprunt.")
def rendre(self):
if not self.disponible:
self.disponible = True
print(f"Le livre '{self.titre}' a été rendu.")
else:
print(f"Le livre '{self.titre}' était déjà disponible.")
class LivreNumerique(Livre): # Hérite de Livre
def __init__(self, titre, auteur, annee_publication, taille_mo, disponible=True):
super().__init__(titre, auteur, annee_publication, disponible) # Appel du constructeur parent
self.taille_mo = taille_mo # Nouvel attribut spécifique
b) La méthode afficher_details est redéfinie pour ajouter l'information sur la taille. On peut appeler la méthode parente avec super().afficher_details() puis ajouter les informations supplémentaires, ou reconstruire complètement l'affichage.
class LivreNumerique(Livre):
def __init__(self, titre, auteur, annee_publication, taille_mo, disponible=True):
super().__init__(titre, auteur, annee_publication, disponible)
self.taille_mo = taille_mo
def afficher_details(self):
# On peut réutiliser la logique de la classe parente ou la redéfinir
etat = "disponible" if self.disponible else "emprunté"
print(f"'{self.titre}' (numérique) par {self.auteur}, publié en {self.annee_publication}. Taille : {self.taille_mo} Mo. État : {etat}.")
c) Instanciation et affichage.
e_book = LivreNumerique("Dune", "Frank Herbert", 1965, 25.5)
e_book.afficher_details()
e_book.emprunter() # La méthode emprunter de Livre est héritée
e_book.afficher_details()
Résultat :
'Dune' (numérique) par Frank Herbert, publié en 1965. Taille : 25.5 Mo. État : disponible.
Le livre 'Dune' a été emprunté.
'Dune' (numérique) par Frank Herbert, publié en 1965. Taille : 25.5 Mo. État : emprunté.
Astuce : L'héritage est un excellent moyen de réutiliser du code et d'établir des relations "est un type de" (un livre numérique est un type de livre).
Exercice 6 : Polymorphisme
Crée une fonction decrire_objet qui prend un objet en paramètre et appelle sa méthode afficher_details(). Teste cette fonction avec un objet Livre et un objet LivreNumerique.
a) Implémente la fonction decrire_objet.
b) Appelle decrire_objet avec une instance de Livre et une instance de LivreNumerique. Observe comment la méthode afficher_details correcte est appelée pour chaque type d'objet.
Barème indicatif : 3 points
Correction :
a) Le polymorphisme permet à des objets de classes différentes d'être traités de manière uniforme s'ils partagent une interface commune (ici, la méthode afficher_details).
def decrire_objet(objet):
objet.afficher_details()
b) Test de la fonction avec différentes instances.
# Création des instances
livre_physique = Livre("Fondation", "Isaac Asimov", 1951)
livre_numerique = LivreNumerique("Neuromancien", "William Gibson", 1984, 12.8)
# Appel de la fonction polymorphique
print("--- Description des objets via la fonction decrire_objet ---")
decrire_objet(livre_physique)
decrire_objet(livre_numerique)
Résultat :
--- Description des objets via la fonction decrire_objet ---
'Fondation' par Isaac Asimov, publié en 1951. État : disponible.
'Neuromancien' (numérique) par William Gibson, publié en 1984. Taille : 12.8 Mo. État : disponible.
Point méthode : C'est la beauté du polymorphisme : tu peux écrire du code générique qui fonctionne avec n'importe quel objet, du moment qu'il implémente la méthode attendue. Python utilise le "duck typing" ("Si ça marche comme un canard et ça cancane comme un canard, c'est un canard").
Exercice 7 : Composition de Classes
Plutôt que d'hériter, tu peux composer des objets. Crée une classe Auteur (avec nom, prenom, date_naissance) et modifie la classe Livre pour qu'elle contienne un objet Auteur au lieu de l'attribut auteur en chaîne de caractères.
a) Crée la classe Auteur.
b) Modifie la classe Livre pour qu'elle accepte un objet Auteur dans son constructeur. Adapte la méthode afficher_details pour afficher le nom complet de l'auteur à partir de l'objet Auteur.
c) Instancie un objet Auteur, puis un objet Livre en lui passant l'objet Auteur. Affiche les détails du livre.
Barème indicatif : 4 points
Correction :
a) La classe Auteur est simple.
class Auteur:
def __init__(self, nom, prenom, date_naissance):
self.nom = nom
self.prenom = prenom
self.date_naissance = date_naissance
def nom_complet(self):
return f"{self.prenom} {self.nom}"
b) La classe Livre est modifiée. L'attribut self.auteur stocke maintenant un objet Auteur.
import datetime
class Livre:
def __init__(self, titre, auteur_obj, annee_publication, disponible=True): # auteur_obj est un objet Auteur
self.titre = titre
self.auteur = auteur_obj # Stocke l'objet Auteur
self.disponible = disponible
self.annee_publication = annee_publication
@property
def annee_publication(self):
return self._annee_publication
@annee_publication.setter
def annee_publication(self, value):
annee_actuelle = datetime.date.today().year
if not isinstance(value, int) or value <= 0 or value > annee_actuelle:
if not hasattr(self, '_annee_publication'):
self._annee_publication = annee_actuelle
print(f"Attention : L'année de publication '{value}' est invalide. Elle doit être un entier positif et non future. La valeur ne sera pas modifiée.")
else:
self._annee_publication = value
def afficher_details(self):
etat = "disponible" if self.disponible else "emprunté"
# Utilisation de la méthode nom_complet de l'objet Auteur
print(f"'{self.titre}' par {self.auteur.nom_complet()}, publié en {self.annee_publication}. État : {etat}.")
def emprunter(self):
if self.disponible:
self.disponible = False
print(f"Le livre '{self.titre}' a été emprunté.")
else:
print(f"Le livre '{self.titre}' n'est pas disponible pour l'emprunt.")
def rendre(self):
if not self.disponible:
self.disponible = True
print(f"Le livre '{self.titre}' a été rendu.")
else:
print(f"Le livre '{self.titre}' était déjà disponible.")
c) Instanciation des objets.
auteur_tolkien = Auteur("Tolkien", "J.R.R.", "03/01/1892")
livre_compose = Livre("Le Hobbit", auteur_tolkien, 1937)
livre_compose.afficher_details()
Résultat :
'Le Hobbit' par J.R.R. Tolkien, publié en 1937. État : disponible.
Point méthode : La composition est souvent préférée à l'héritage quand il s'agit d'une relation "a un" (un livre a un auteur). Elle favorise une plus grande flexibilité et réduit la complexité des hiérarchies d'héritage.
Exercice 8 : Méthodes de Classe et Méthodes Statiques
Ajoute à la classe Livre :
a) Une méthode de classe (@classmethod) creer_livre_avec_annee_actuelle qui prend le titre et l'auteur et crée un livre avec l'année de publication par défaut à l'année courante.
b) Une méthode statique (@staticmethod) verifier_validite_titre qui prend un titre en chaîne de caractères et retourne True si le titre n'est pas vide et fait plus de 2 caractères, False sinon.
c) Utilise ces méthodes pour créer un livre et vérifier la validité d'un titre.
Barème indicatif : 4 points
Correction :
a) Une méthode de classe reçoit la classe elle-même (souvent nommée cls) comme premier argument, ce qui lui permet d'accéder aux attributs de classe ou de créer des instances de cette classe.
b) Une méthode statique ne reçoit aucun argument spécial (ni self, ni cls). Elle se comporte comme une fonction normale mais est logiquement groupée avec la classe.
import datetime
class Livre:
def __init__(self, titre, auteur_obj, annee_publication, disponible=True):
self.titre = titre
self.auteur = auteur_obj
self.disponible = disponible
self.annee_publication = annee_publication
@property
def annee_publication(self):
return self._annee_publication
@annee_publication.setter
def annee_publication(self, value):
annee_actuelle = datetime.date.today().year
if not isinstance(value, int) or value <= 0 or value > annee_actuelle:
if not hasattr(self, '_annee_publication'):
self._annee_publication = annee_actuelle
print(f"Attention : L'année de publication '{value}' est invalide. Elle doit être un entier positif et non future. La valeur ne sera pas modifiée.")
else:
self._annee_publication = value
def afficher_details(self):
etat = "disponible" if self.disponible else "emprunté"
print(f"'{self.titre}' par {self.auteur.nom_complet()}, publié en {self.annee_publication}. État : {etat}.")
def emprunter(self):
if self.disponible:
self.disponible = False
print(f"Le livre '{self.titre}' a été emprunté.")
else:
print(f"Le livre '{self.titre}' n'est pas disponible pour l'emprunt.")
def rendre(self):
if not self.disponible:
self.disponible = True
print(f"Le livre '{self.titre}' a été rendu.")
else:
print(f"Le livre '{self.titre}' était déjà disponible.")
@classmethod
def creer_livre_avec_annee_actuelle(cls, titre, auteur_obj):
annee_actuelle = datetime.date.today().year
return cls(titre, auteur_obj, annee_actuelle) # Appelle le constructeur de la classe (cls)
@staticmethod
def verifier_validite_titre(titre):
return isinstance(titre, str) and len(titre) > 2
c) Utilisation des nouvelles méthodes.
auteur_orwell = Auteur("Orwell", "George", "25/06/1903")
# Utilisation de la méthode de classe
livre_moderne = Livre.creer_livre_avec_annee_actuelle("Un nouveau monde", auteur_orwell)
livre_moderne.afficher_details()
print("-" * 20)
# Utilisation de la méthode statique
titre_valide = "Le Grand Sommeil"
titre_invalide_court = "Un"
titre_invalide_vide = ""
print(f"'{titre_valide}' est valide ? {Livre.verifier_validite_titre(titre_valide)}")
print(f"'{titre_invalide_court}' est valide ? {Livre.verifier_validite_titre(titre_invalide_court)}")
print(f"'{titre_invalide_vide}' est valide ? {Livre.verifier_validite_titre(titre_invalide_vide)}")
Résultat :
'Un nouveau monde' par George Orwell, publié aujourd'hui. État : disponible.
--------------------
'Le Grand Sommeil' est valide ? True
'Un' est valide ? False
'' est valide ? False
Point méthode : Les méthodes de classe sont utiles pour des constructeurs alternatifs, tandis que les méthodes statiques sont pour des utilitaires liés à la classe mais qui n'ont pas besoin d'accéder à l'état de l'instance ou de la classe.
Exercice 9 : Méthodes Spéciales (Dunder Methods)
Ajoute à ta classe Livre les méthodes spéciales suivantes :
a) __str__ : Cette méthode doit retourner une représentation textuelle conviviale de l'objet Livre (ex: "Titre : [titre], Auteur : [auteur.nom_complet()], Année : [année]").
b) __repr__ : Cette méthode doit retourner une représentation textuelle permettant de recréer l'objet (ex: "Livre('Titre', AuteurObj, 2023)").
c) __eq__ : Permet de comparer deux livres par leur titre et leur auteur. Deux livres sont considérés égaux s'ils ont le même titre et le même auteur.
d) Teste ces méthodes avec des objets Livre.
Barème indicatif : 4 points
Correction :
Les méthodes spéciales, ou "dunder methods" (pour "double underscore"), permettent de définir le comportement de tes objets avec des opérations Python natives (impression, comparaison, etc.).
import datetime
class Auteur:
def __init__(self, nom, prenom, date_naissance):
self.nom = nom
self.prenom = prenom
self.date_naissance = date_naissance
def nom_complet(self):
return f"{self.prenom} {self.nom}"
def __repr__(self): # Utile pour __repr__ de Livre
return f"Auteur('{self.nom}', '{self.prenom}', '{self.date_naissance}')"
class Livre:
def __init__(self, titre, auteur_obj, annee_publication, disponible=True):
self.titre = titre
self.auteur = auteur_obj
self.disponible = disponible
self.annee_publication = annee_publication
@property
def annee_publication(self):
return self._annee_publication
@annee_publication.setter
def annee_publication(self, value):
annee_actuelle = datetime.date.today().year
if not isinstance(value, int) or value <= 0 or value > annee_actuelle:
if not hasattr(self, '_annee_publication'):
self._annee_publication = annee_actuelle
print(f"Attention : L'année de publication '{value}' est invalide. Elle doit être un entier positif et non future. La valeur ne sera pas modifiée.")
else:
self._annee_publication = value
def afficher_details(self):
etat = "disponible" if self.disponible else "emprunté"
print(f"'{self.titre}' par {self.auteur.nom_complet()}, publié en {self.annee_publication}. État : {etat}.")
def emprunter(self):
if self.disponible:
self.disponible = False
print(f"Le livre '{self.titre}' a été emprunté.")
else:
print(f"Le livre '{self.titre}' n'est pas disponible pour l'emprunt.")
def rendre(self):
if not self.disponible:
self.disponible = True
print(f"Le livre '{self.titre}' a été rendu.")
else:
print(f"Le livre '{self.titre}' était déjà disponible.")
@classmethod
def creer_livre_avec_annee_actuelle(cls, titre, auteur_obj):
annee_actuelle = datetime.date.today().year
return cls(titre, auteur_obj, annee_actuelle)
@staticmethod
def verifier_validite_titre(titre):
return isinstance(titre, str) and len(titre) > 2
# a) Méthode __str__
def __str__(self):
return f"Titre : {self.titre}, Auteur : {self.auteur.nom_complet()}, Année : {self.annee_publication}"
# b) Méthode __repr__
def __repr__(self):
# Assure-toi que __repr__ d'Auteur est aussi défini pour un bon affichage
return f"Livre('{self.titre}', {repr(self.auteur)}, {self.annee_publication}, disponible={self.disponible})"
# c) Méthode __eq__
def __eq__(self, other):
if not isinstance(other, Livre):
return NotImplemented # Indique la comparaison n'est pas implémentée pour ce type
return self.titre == other.titre and self.auteur.nom_complet() == other.auteur.nom_complet()
d) Test des méthodes.
auteur_king = Auteur("King", "Stephen", "21/09/1947")
livre_it = Livre("Ça", auteur_king, 1986)
livre_shining = Livre("Shining", auteur_king, 1977)
livre_it_bis = Livre("Ça", auteur_king, 2000) # Même titre, même auteur mais année différente
print("--- Test de __str__ ---")
print(livre_it)
print("\n--- Test de __repr__ ---")
print(repr(livre_shining))
print("\n--- Test de __eq__ ---")
print(f"livre_it == livre_shining : {livre_it == livre_shining}")
print(f"livre_it == livre_it_bis : {livre_it == livre_it_bis}")
print(f"livre_it == 'une chaîne' : {livre_it == 'une chaîne'}")
Résultat :
--- Test de __str__ ---
Titre : Ça, Auteur : Stephen King, Année : 1986
--- Test de __repr__ ---
Livre('Shining', Auteur('King', 'Stephen', '21/09/1947'), 1977, disponible=True)
--- Test de __eq__ ---
livre_it == livre_shining : False
livre_it == livre_it_bis : True
livre_it == 'une chaîne' : False
Astuce : __str__ est pour l'utilisateur final (lisible), __repr__ est pour le développeur (non ambiguë et si possible recréable). __eq__ te donne un contrôle précis sur la notion d'égalité entre tes objets.
Comment ORBITECH Peut T'aider
ORBITECH AI Academy met à ta disposition des outils concrets pour réviser plus efficacement et progresser à ton rythme.
- Générateur de Quiz : crée des quiz personnalisés pour tester tes connaissances et identifier tes lacunes.
- Générateur d'Exercices : crée des exercices d'entraînement adaptés à ton niveau avec corrections détaillées.
- Générateur de Résumés : transforme tes cours en fiches de révision claires et structurées.
- Générateur de Mind Maps : visualise et organise tes idées avec des cartes mentales générées automatiquement.
Tous ces outils sont disponibles sur ta plateforme ORBITECH. Connecte-toi et explore ceux qui correspondent le mieux à tes besoins !
Commencer gratuitement