{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Programmation orientée objet _ Exercices"},{"metadata":{},"cell_type":"markdown","source":"## Exercice 1 : la voiture \nOn considère une classe Voiture dont le code en python est le suivant :"},{"metadata":{"trusted":false},"cell_type":"code","source":"class Voiture :\n def __init__(self, annee, coul, vmax) :\n self.annee = annee \n self.couleur = coul\n self.vitesse_max = vmax\n self.age = 2021 - self.annee\n\n def petite_annonce(self) :\n return \"À vendre voiture \"+ str(self.couleur)+ \" de \" + str(self.annee) +\\\\\n \", vitesse maximale \"+ str(self.vitesse_max)+ \" km/h.\"","execution_count":2,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":" 1. Quels sont les attributs des instances de cette classe ? "},{"metadata":{},"cell_type":"markdown","source":""},{"metadata":{},"cell_type":"markdown","source":"2. Quelles sont les méthodes ?"},{"metadata":{},"cell_type":"markdown","source":""},{"metadata":{},"cell_type":"markdown","source":"3. Le type des attributs n'est pas documenté dans le code ni le rôle de la méthode.\n \n Proposer une documentation."},{"metadata":{},"cell_type":"markdown","source":"4. Ecrire dans la cellule qui suit le code nécessaire à la création d'un objet `ma_voiture` datant de 1957, de couleur grise et roulant à 110 km/h maximum.\n Appliquer la méthode `petite_annonce` à cette instance.\n"},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Pour aller plus loin :**\n\n 4. Ajouter à la classe `Voiture` une méthode `est_ancienne(self)` qui renvoie `True` si la voiture a plus de 30 ans, `False` sinon (on utilisera l'attribut `age`).\n\n 5. Ajouter un nouvel attribut `proprietaire` (une chaîne de caractères, valant `None` par défaut à la création) ainsi qu'une méthode `changer_proprietaire(self, nom)` qui met à jour cet attribut.\n"},{"metadata":{"trusted":false},"cell_type":"code","source":"# Questions 4 à 5 : jeu de tests\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":" 6. Écrire une fonction (extérieure à la classe) `plus_rapide(v1, v2)` qui prend deux instances de `Voiture` et renvoie celle dont la vitesse maximale est la plus élevée."},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Exercice 2 : La serrure.\nUne serrure fonctionne avec un code secret qui est une séquence de 4 chiffres.
La serrure peut être verrouillée ou déverrouillée.
\nA la création de la serrure, elle est en état bloquée
Pour déverrouiller la serrure il faut fournir le bon code."},{"metadata":{},"cell_type":"markdown","source":" 1. Compléter la classe Serrure.\n Cette classe doit implémenter les méthodes \n - `verrouiller()` met la serrure en etat verrouillee,\n - `deverrouiller(code) ` deverouille la serrure si le code est egale au code secret. \n \n renvoie True si le deverouillage a réussi, False sinon\n - `changer_code_secret(nouveau_code)` remplace le code secret par code si c'est un code valide,\n renvoie True si le changement a réussi, False sinon\n \n Cette classe doit permettre d'écrire le code suivant :\n \n `>>> ma_serrure = Serrure(1925) # le code de la serrure est 1925`
\n `>>> ma_serrure.verouillee # etat de la serrure` \n `True`
\n `>>> ma_serrure.deverouiller(1965) # tentative de deverouillage`
\n ` False` \n \n 2. Compléter le code de chaque méthode.\n 3. Documenter le code\n 4. Proposer un petit scénario de test"},{"metadata":{"trusted":false},"cell_type":"code","source":"# Question 1 , 2 et 3\nclass Serrure:\n \n def __init__(self,code):\n self.code=code\n self.bloquee=True\n \n def verrouiller(self):\n pass \n \n def deverouiller(code):\n pass\n\n def changer_code(self,nouveau_code):\n pass\n ","execution_count":2,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# Question 4\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Pour aller plus loin :**\n\n 5. Ajouter un attribut `nb_essais` qui compte le nombre de tentatives de déverrouillage incorrectes consécutives.\n\n 6. Modifier `deverrouiller` pour que la serrure se bloque (attribut `bloquee` mis à `True`) après 3 échecs consécutifs. Tant que la serrure est bloquée, `deverrouiller` doit renvoyer `False`, même si le bon code est fourni.\n\n 7. Ajouter une méthode `debloquer(self, code_maitre)` qui permet de débloquer la serrure à l'aide d'un code maître, fixé une fois pour toutes à la création de l'objet (paramètre supplémentaire de `__init__`).\n\n 8. Proposer un scénario de test qui provoque le blocage de la serrure puis la débloque à l'aide du code maître."},{"metadata":{"trusted":false},"cell_type":"code","source":"# Questions 5 à 8","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Exercice 3 : Le coffre fort.\nUn coffre fort contient un certain montant en euros.
\nCe montant est nul si le coffre est vide.
\nLe coffre peut être ouvert ou fermé.
\nSi le coffre est ouvert, on peut le consulter, y déposer de l’argent ou en retirer.
\nSi le coffre est fermé, ces opérations sont impossibles.
\nOn ne peut pas retirer plus que ce que contient le coffre.\n\n 1. Compléter le code de la classe Coffre\n "},{"metadata":{"trusted":false},"cell_type":"code","source":"class Coffre :\n \"\"\" Une classe pour les coffres-forts \n attributs : \n ouvert : bool \n contenu : float\n \"\"\" \n \n def __init__(self, montant) :\n \"\"\" Coffre(montant) , crée un coffre fermé avec montant comme contenu initial \"\"\"\n assert montant >=0 # Le montant initial doit être positif ou nul\n self.ouvert = False # par défaut le coffre est fermé\n self.contenu = montant\n \n def ouvrir(self) :\n \"\"\" met le coffre en etat ouvert \"\"\"\n pass\n \n def fermer(self) :\n \"\"\" met le coffre en etat fermé \"\"\"\n pass\n \n def consulter(self) :\n \"\"\" donne le contenu du coffre s'il est ouvert, -1 sinon\"\"\"\n pass\n \n def deposer(self, montant) :\n \"\"\"ajoute le montant au contenu si le coffre est ouvert. Renvoie le montant déposé (0 si fermé) \"\"\"\n pass\n \n def retirer(self, montant) :\n \"\"\" retire le montant du coffre s'il est ouvert . Renvoie le montant déposé (0 si fermé) \"\"\"\n pass\n ","execution_count":6,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":" 2. Ecrire un scénario utilisant cette classe pour tester les différentes méthodes.\n "},{"metadata":{"trusted":false},"cell_type":"code","source":"# scénario ","execution_count":1,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Pour aller plus loin :**\n\n 3. Ajouter un attribut `historique` (une liste, vide à la création) qui garde la trace de toutes les opérations réussies sous forme de tuples `(type_operation, montant)`, par exemple `(\"depot\", 100)` ou `(\"retrait\", 50)`.\n\n 4. Tester avec un scenario cette nouvelle fonctionnalité"},{"metadata":{"trusted":false},"cell_type":"code","source":"# Questions 4","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Exercice 4 : Le thermostat\nUn thermostat régule la température d'une pièce. Il possède une température de consigne (la température souhaitée) et mémorise la dernière température mesurée. Il peut être en marche ou à l'arrêt.\n\nQuand le thermostat est **en marche** et qu'on lui transmet une nouvelle mesure de température :\n- si la température mesurée est strictement inférieure à la consigne, le chauffage se met en marche,\n- sinon, le chauffage s'arrête.\n\nQuand le thermostat est **à l'arrêt**, le chauffage ne se déclenche jamais, quelle que soit la température mesurée.\n\nOn souhaite pouvoir écrire :\n\n`>>> thermo = Thermostat(19) # consigne de 19°C`
\n`>>> thermo.allumer()`
\n`>>> thermo.mesurer_temperature(17)`
\n` 'Chauffage ON'`
\n`>>> thermo.mesurer_temperature(21)`
\n` 'Chauffage OFF'`
\n`>>> thermo.eteindre()`
\n`>>> thermo.mesurer_temperature(10)`
\n` 'Thermostat éteint'`
\n\n 1. Quels sont les attributs et les méthodes des instances de cette classe ?\n 2. Ecrire le squelette de la classe `Thermostat`.\n 3. Compléter le code des méthodes `__init__`, `allumer`, `eteindre`, `mesurer_temperature` et `changer_consigne(nouvelle_consigne)`.\n 4. Documenter le code (docstrings).\n 5. Proposer un scénario de test reprenant l'exemple ci-dessus."},{"metadata":{"trusted":false},"cell_type":"code","source":"# Questions 1 à 5","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Pour aller plus loin :**\n\n 6. Ajouter un attribut `historique` qui conserve, sous forme de liste, toutes les températures mesurées depuis la création du thermostat.\n\n 7. Ajouter un mode `\"absence\"` : la méthode `activer_absence()` abaisse automatiquement la consigne de 5°C (et la mémorise pour pouvoir la restaurer), tandis que `desactiver_absence()` restaure la consigne initiale.\n\n 8. Écrire un scénario de test qui illustre l'historique des mesures et le mode absence."},{"metadata":{"trusted":false},"cell_type":"code","source":"# Questions 6 à 8","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Exercice 5 : Le temps\nOn souhaite représenter une durée exprimée en heures, minutes et secondes (comme un chronomètre), et pouvoir additionner deux durées entre elles.\n\n**Attention aux retenues** : dès que le nombre de secondes atteint 60, il faut ajouter 1 minute et garder le reste ; de même, dès que le nombre de minutes atteint 60, il faut ajouter 1 heure et garder le reste.\n\nOn souhaite pouvoir écrire :\n\n`>>> t1 = Temps(1, 45, 30) # 1h 45min 30s`
\n`>>> t2 = Temps(0, 30, 45) # 30min 45s`
\n`>>> t1.ajouter(t2)`
\n`>>> t1.afficher()`
\n` 2:16:15`
\n\n 1. Quels sont les attributs des instances de cette classe ? Quelle méthode permet d'additionner deux temps ?\n 2. Ecrire le squelette de la classe `Temps`.\n 3. Compléter le code de `__init__` et de `ajouter(self, autre)`, qui ajoute la durée `autre` (un autre objet `Temps`) à l'instance courante, en gérant correctement les retenues.\n 4. Définir une méthode `afficher` affiche le temps sous la forme `H:MM:SS` (minutes et secondes toujours sur 2 chiffres, par exemple `2:05:07`).\n 5. Documenter le code (docstrings) et proposer un scénario de test reprenant l'exemple ci-dessus."},{"metadata":{"trusted":false},"cell_type":"code","source":"# Questions 1 à 5","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Pour aller plus loin :**\n\n 6. Ajouter une méthode `en_secondes(self)` qui renvoie la durée totale exprimée uniquement en secondes.\n\n 7. Ajouter une méthode `soustraire(self, autre)` qui soustrait la durée `autre` à l'instance courante (on pourra utiliser `en_secondes` pour simplifier les calculs, et on supposera que le résultat reste positif ou nul).\n\n \n 8. Écrire un scénario de test illustrant `en_secondes`, `soustraire`."},{"metadata":{"trusted":true},"cell_type":"code","source":"# Questions 6 à 8","execution_count":1,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Exercice 6 : La playlist musicale\nUne playlist contient une liste ordonnée de titres (des chaînes de caractères). On peut ajouter un titre à la fin de la playlist, en supprimer un, et faire défiler la lecture titre par titre.\n\nÀ tout moment, la playlist connaît le titre \"en cours de lecture\" (le premier titre par défaut, tant qu'aucune lecture n'a commencé).\n\nOn souhaite pouvoir écrire :\n\n`>>> pl = Playlist(\"Révisions\")`
\n`>>> pl.ajouter_titre(\"Titre A\")`
\n`>>> pl.ajouter_titre(\"Titre B\")`
\n`>>> pl.titre_courant()`
\n` 'Titre A'`
\n`>>> pl.titre_suivant()`
\n` 'Titre B'`
\n`>>> pl.titre_suivant() # plus de titre après le dernier`
\n` None`
\n\n 1. Quels sont les attributs et les méthodes des instances de cette classe ?\n 2. Ecrire le squelette de la classe `Playlist`.\n 3. Compléter le code des méthodes `__init__`, `ajouter_titre(titre)`, `supprimer_titre(titre)`, `titre_courant()` et `titre_suivant()`.\n 4. Documenter le code (docstrings).\n 5. Proposer un scénario de test reprenant l'exemple ci-dessus, y compris le cas où l'on supprime le titre en cours de lecture."},{"metadata":{"trusted":false},"cell_type":"code","source":"# Questions 1 à 5","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Pour aller plus loin :**\n\n 6. Ajouter un mode `\"lecture en boucle\"` (attribut `boucle`, `False` par défaut) : lorsqu'il est activé, `titre_suivant()` revient au premier titre après le dernier au lieu de renvoyer `None`.\n\n 7. Écrire un scénario de test illustrant le mode boucle "},{"metadata":{"trusted":false},"cell_type":"code","source":"# Questions 6 à 7","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":" "},{"metadata":{},"cell_type":"markdown","source":" "}],"metadata":{"kernelspec":{"display_name":"Python [conda env:base] *","language":"python","name":"conda-base-py"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.13.9"}},"nbformat":4,"nbformat_minor":2}