Épreuve pratique NSI

Sujet n° 17 · Session 2026 · 1 heure

Le budget d'un club de handball

Un club de handball veut vérifier son solde de fin d'année. Le candidat totalise recettes et dépenses, écrit les tests, puis découvre qu'un simple range oublie décembre : le club se croyait bénéficiaire, il est en déficit.

  • Liste de dictionnaires
  • Accumulateur
  • Tests et assertions
  • Bornes de range
  • Fichier CSV

Mise en situationLes mouvements

Chaque mouvement budgétaire est un dictionnaire : 'type' ('dépense' ou 'recette'), 'catégorie' (subventions, sponsoring, billetterie, marketing, salaires, déplacements, fonctionnement, cotisations ou autres_charges), 'montant' (flottant positif, en euros) et 'mois' (entier de 1 à 12).

Deux jeux de données sont fournis : la liste mouvements_test ci-dessous, définie dans le code, et le fichier budget_complet.csv de plus de 2 000 mouvements, chargé par lire_mouvements_depuis_csv.

TypeCatégorieMontantMois
recettecotisations1 200 €1
recettebilletterie300 €6
dépensefonctionnement450 €6
dépensedéplacements200 €12
dépensesalaires1 500 €12
recettesubventions800 €12

mouvements_test

Toutes les cellules de cette page partagent le même Python, comme un notebook : une fonction écrite à une question sert aux suivantes. Maj + Entrée exécute la cellule.

1

Question 1Total par type

Écrire la fonction total_par_type(mouvements, type_mouvement) qui prend en paramètres une liste de mouvements et une chaîne de caractères (parmi 'dépense' ou 'recette'). Cette fonction doit renvoyer la somme totale des montants correspondant à ce type précis. La fonction renverra 0 si aucun mouvement ne correspond.

Créer ensuite une fonction test_total() contenant au moins deux assertions pour valider le bon fonctionnement de votre code sur le jeu de données mouvements_test (par exemple, le total des recettes attendu est de 2300.0).

Appel professeur

À demander au candidat

  1. Quels sont les paramètres de total_par_type et leurs types ? Quel est le type de la valeur renvoyée ?
  2. Pourquoi == et non = dans m['type'] == type_mouvement ? Quel est le type de cette expression ?
  3. Que se passe-t-il si une assertion de test_total échoue ? Quelle erreur est levée ?
Point de vigilance

Initialiser l'accumulateur à 0 garantit le résultat 0, et non None, quand aucun mouvement ne correspond.

Résultats attendus
Recettes du jeu de test
2 300 €
Dépenses du jeu de test
2 150 €
2

Question 2Tester le solde annuel

La fonction solde_annuel(mouvements), déjà codée dans le fichier fourni, est censée calculer le bilan financier de l'année en faisant la somme des soldes de chaque mois (recettes totales moins dépenses totales). Si le solde annuel est positif, le club dégage des bénéfices. S'il est négatif, le club est en déficit.

Calculer manuellement le solde annuel attendu pour la liste mouvements_test. Écrire ensuite une fonction test_solde_annuel() contenant une assertion qui vérifie que la fonction solde_annuel(mouvements_test) renvoie bien ce résultat théorique. Exécuter ce test.

Appel professeur

À demander au candidat

  1. Détaillez votre calcul du solde attendu : quels mouvements sont des recettes, lesquels des dépenses, et de quels mois ?
Point de vigilance

Le calcul à la main doit précéder le code : 2 300 − 2 150 = 150 €.

Résultats attendus
Solde attendu
150 €
Renvoyé par le code fourni
1 050 €
3

Question 3Le mois oublié

L'exécution du test précédent lève une erreur : le résultat renvoyé par la fonction solde_annuel ne correspond pas à la réalité comptable.

Analyser le code de la fonction solde_annuel pour identifier la source de cette erreur logique, expliquer pourquoi certains mouvements ont été ignorés, puis proposer une correction. La fonction se trouve à la question 2. Appliquer ensuite votre fonction corrigée sur le fichier budget_complet.csv pour annoncer le véritable solde du club au professeur.

Appel professeur

À demander au candidat

  1. Quelles valeurs produit range(1, 12) ? Laquelle manque pour couvrir l'année ?
  2. Pourquoi la fonction ne lève-t-elle aucune erreur malgré ce bug ? En quoi le test était-il indispensable ?
  3. Pourquoi lire_mouvements_depuis_csv convertit-elle mois en entier ? Que deviendrait m['mois'] == mois avec une chaîne ?
Point de vigilance

L'erreur est silencieuse : décembre est ignoré, et avec lui 1 700 € de dépenses et 800 € de recettes du jeu de test.

Résultats attendus
Fichier complet, code fourni
+14 315,37 €
Fichier complet, corrigé
−3 423,17 € (déficit)

Le fichier du candidat

Le jour de l'épreuve, le candidat travaille dans un seul fichier. Ce bouton rassemble vos cellules dans l'ordre, telles qu'elles sont à l'écran, en un analyse_budget.py à ouvrir dans votre éditeur habituel.

Chargement de Python…