Un corrigé pédagogique pour comprendre et justifier vos réponses. Les conseils de rédaction ne constituent pas un barème officiel détaillé.
Application
Refuge de renards, objets et import CSV typé
Le refuge conserve les animaux dans une liste d’objets Renard. Chaque animal possède un identifiant entier, un nom, un poids flottant en kilogrammes et une date d’arrivée au format AAAA-MM-JJ. Le Refuge possède un nom, une adresse et liste_renards. Les données CSV utilisent le point-virgule. Le tableau ci-dessous reproduit l’extrait illustratif du PDF ; les noms du fichier réellement livré diffèrent, par exemple l’identifiant 101 y porte le nom Zorro. Les calculs du corrigé utilisent le fichier téléchargé.
| id | nom (extrait du PDF) | poids | date_arrivee |
|---|---|---|---|
| 101 | Édgar | 6.5 | 2023-01-15 |
| 102 | César | 5.8 | 2023-02-10 |
| 103 | Gérard | 7.2 | 2023-03-05 |
| 104 | Sybille | 4.9 | 2024-11-20 |
Le dossier comporte le sujet et les fichiers listés dans les téléchargements. Les codes de départ sont reproduits ci-dessous. Travaillez sur une copie. Les appels professeur signalés dans les questions servent à présenter votre démarche ; vous pouvez aussi demander de l’aide en cas de difficulté.
Code fourni : gestion_refuge.py
import csv
class Renard:
"""
Classe représentant un renard dans le refuge.
Attributs : identifiant, nom, poids, date_arrivee.
"""
def __init__(self, identifiant, nom, poids, date_arrivee):
pass # Question 1 à compléter
def __str__(self):
pass # Question 2 à compléter
class Refuge:
"""
Classe représentant le refuge contenant la liste des renards.
"""
def __init__(self, nom, adresse):
self.nom = nom
self.adresse = adresse
self.liste_renards = []
def recueillir(self, un_renard):
"""
Méthode d'ajout d'un renard au refuge.
"""
self.liste_renards.append(un_renard)
def lister_peu_corpulents(self):
"""
Méthode qui renvoie une liste des Renards dont le poids est < 6.0 kg.
"""
return [renard for renard in self.liste_renards if renard.poids < 6.0]
def pourcentage_peu_corpulents(self):
"""
Méthode qui renvoie le pourcentage des renards peu corpulents.
"""
if len(self.liste_renards) == 0:
return 0.0
return len(self.lister_peu_corpulents()) / len(self.liste_renards) * 100
def importer_donnees(self, nom_fichier):
"""
Fonction qui importe les données des renards à partir d'un fichier CSV.
"""
print(f"Tentative d'importation depuis {nom_fichier}...")
with open(nom_fichier, 'r', encoding='utf-8') as f:
lignes = csv.DictReader(f, delimiter=';')
for ligne in lignes:
renard = Renard(ligne['id'], ligne['nom'],
ligne['poids'], ligne['date_arrivee'])
self.recueillir(renard)
Question 1
#Écrire le constructeur __init__ de Renard.
Indice
Les valeurs doivent rester disponibles après la fin de l’appel.
Comprendre la correction
def __init__(self, identifiant, nom, poids, date_arrivee):
self.identifiant = identifiant
self.nom = nom
self.poids = poids
self.date_arrivee = date_arriveeChaque paramètre est stocké dans l’attribut homonyme de l’instance. Le constructeur ne doit pas utiliser de variable globale. Ici son contrat reçoit déjà les bons types ; l’import CSV sera responsable de convertir ses chaînes avant de créer l’objet.
Question 2
#Écrire __str__ pour renvoyer exactement "Renard ID [id] - [Nom] (Arrivé le [date_arrivee])". Créer renard 1 : id 200, Oscar,5.1 kg, arrivé le 1 er janvier 2026 ; afficher son instance.
PythonDonner une représentation lisible à un objetÉcrivez votre solution et mettez-la à l’épreuve
Complétez __str__ dans la classe Renard. Renvoyez exactement la forme Renard ID 200 - Oscar (Arrivé le 2026-01-01), en utilisant les attributs de l’instance. Le constructeur est fourni. La méthode doit renvoyer une chaîne, pas afficher avec print. Ce défi isole la représentation d’objet, sans import CSV.
class Renard:
def __init__(self, identifiant, nom, poids, date_arrivee):
self.identifiant = identifiant
self.nom = nom
self.poids = poids
self.date_arrivee = date_arrivee
def __str__(self):
# Complétez cette méthode
pass
Les cas de test proposés :
- Oscar, comme dans le sujet : La ponctuation et les espaces font partie de la forme demandée.
- Une autre instance : Le résultat doit provenir des attributs, pas de l’exemple recopié.
- La méthode renvoie du texte : Un print seul renvoie
Noneet viole le contrat de__str__. - Changement de nom : La représentation reflète l’état actuel de l’objet sans changer son poids.
Indice
Une méthode spéciale __str__ doit retourner str.
Comprendre la correction
def __str__(self):
return f'Renard ID {self.identifiant} - {self.nom} (Arrivé le {self.date_arrivee})'renard1 = Renard(200, 'Oscar', 5.1, '2026-01-01')
print(renard1)
assert str(renard1) == 'Renard ID 200 - Oscar (Arrivé le 2026-01-01)'La méthode doit renvoyer une chaîne. Un print dans __str__ renverrait implicitement None et ferait échouer print(renard 1). Les crochets de la description sont des emplacements à remplacer, pas des caractères à conserver.
Question 3
#Identifier le défaut de importer_donnees concernant les poids et identifiants, corriger, puis créer SOS Goupil,12 rue de la Forêt et importer donnees_renards.csv.
Indice
Observer type(ligne["poids"]) avant la conversion.
Comprendre la correction
csv.DictReader renvoie les cellules sous forme de chaînes, même lorsqu’elles ressemblent à des nombres. Comparer un poids comme "5.8" à 6.0 provoque une erreur de type ; comparer ou additionner des identifiants textuels aurait aussi un autre sens. Les conversions doivent être explicites à la frontière d’entrée.
def importer_donnees(self, nom_fichier):
with open(nom_fichier, 'r', encoding='utf-8', newline='') as fichier:
for ligne in csv.DictReader(fichier, delimiter=';'):
renard = Renard(int(ligne['id']), ligne['nom'],
float(ligne['poids']), ligne['date_arrivee'])
self.recueillir(renard)refuge = Refuge('SOS Goupil', '12 rue de la Forêt')
refuge.importer_donnees('donnees_renards.csv')
assert len(refuge.liste_renards) == 30
assert isinstance(refuge.liste_renards[0].identifiant, int)
assert isinstance(refuge.liste_renards[0].poids, float)Le séparateur et l’encodage sont conservés. Importer deux fois sur la même instance ajouterait les animaux deux fois, car recueillir effectue append : recréer le refuge pour recommencer les tests, ou définir séparément une stratégie de remplacement/dédoublonnage.
L’import constitue une frontière entre deux représentations. Dans le fichier, chaque cellule est du texte ; dans le programme, l’identifiant et le poids ont un rôle numérique. Il est plus simple de convertir une seule fois à l’entrée que de disperser des conversions dans chaque fonction d’analyse. Après un import réussi, toutes les instances doivent respecter les mêmes types. Un affichage comme 6.5 ne permet pas de le prouver : la chaîne '6.5' et le flottant 6.5 se ressemblent à l’écran. D’où l’intérêt d’un test de type et d’un calcul réel après import.
Question 4
#Exécuter lister_peu_corpulents et pourcentage_peu_corpulents. Justifier le résultat en affichant le nombre d’animaux de poids strictement inférieur à 6.0 kg et l’effectif total.
Comprendre la correction
peu_corpulents = refuge.lister_peu_corpulents()
print(len(peu_corpulents), len(refuge.liste_renards))
print(refuge.pourcentage_peu_corpulents())
for renard in peu_corpulents:
print(renard, renard.poids)Le fichier réel contient 30 renards, dont 15 ont un poids strictement inférieur à 6,0 kg. Le pourcentage vaut 15/30×100=50%. Un poids exactement 6,0 est exclu de cette catégorie. La méthode fournie renvoie 0.0 pour un refuge vide ; c’est sa convention de calcul, pas une proportion estimée sur des observations.
Le texte du CSV devient une donnéeUn atelier pour expérimenter
Choisissez une réponse puis confrontez votre intuition à l’explication. Vous pouvez modifier vos choix.
Lire les réponses et leurs explications
- Quel est le type initial de la cellule "5.8" lue par DictReader ?
str. Le lecteur CSV fournit une chaîne.
- Un poids exactement 6.0 kg est-il retenu ?
Non.. 6.0<6.0 est faux.
Appuyez votre explication sur les valeurs et les conditions exactes du programme.
Du seuil au pourcentageUn atelier pour expérimenter
Modifiez le seuil d’analyse sur les trente poids réellement fournis. L’atelier garde la comparaison strictement inférieure ; le seuil demandé au bac reste 6 kg.
Lire le résultat de l’expérience initiale
15 renards sur 30, soit 50.0%.
Une valeur égale au seuil est exclue. Chaque ligne correspond à un poids du CSV, dans son ordre d’origine.
| Identifiant | Poids (kg) | Sous le seuil ? |
|---|---|---|
| 101 | 6.5 | Non |
| 102 | 5.8 | Oui |
| 103 | 7.2 | Non |
| 104 | 4.9 | Oui |
| 105 | 6.1 | Non |
| 106 | 5.5 | Oui |
| 107 | 7.8 | Non |
| 108 | 5.3 | Oui |
| 109 | 6.9 | Non |
| 110 | 4.5 | Oui |
| 111 | 3.2 | Oui |
| 112 | 7 | Non |
| 113 | 6.3 | Non |
| 114 | 5.7 | Oui |
| 115 | 6.6 | Non |
| 116 | 5.1 | Oui |
| 117 | 7.1 | Non |
| 118 | 5.9 | Oui |
| 119 | 6.8 | Non |
| 120 | 4.7 | Oui |
| 121 | 6.4 | Non |
| 122 | 5.6 | Oui |
| 123 | 7.3 | Non |
| 124 | 4.8 | Oui |
| 125 | 6.2 | Non |
| 126 | 5 | Oui |
| 127 | 7.4 | Non |
| 128 | 4.6 | Oui |
| 129 | 6.7 | Non |
| 130 | 5.2 | Oui |
La conversion de type conditionne la validité de toutes les analyses suivantes.
Revoir les notions de cet exercice
Du sujet à la méthode
Votre prochaine séance de révision
- Tester les types à l’import, pas seulement l’apparence de l’affichage.
- Un seuil strict se vérifie avec une valeur exactement égale au seuil.
Retrouver ces notions dans d’autres sujets
Toutes les annales de NSI · Le guide pour préparer le bac NSI 2027
Énoncé : sujet 26_BCG_NSI_12 (PDF). Corrigé et explications pédagogiques proposés par Sofien.
