Cours de Python / Gérer des clés, des valeurs et des totaux avec un dictionnaire

Un dictionnaire Python associe des clés à des valeurs pour retrouver une donnée par son nom. Il convient aux champs d’un enregistrement et aux totaux par catégorie ; choisissez explicitement si une clé absente doit déclencher une erreur ou recevoir une valeur par défaut.

Comprendre les clés et le remplacement d’une valeur

Un littéral de dictionnaire place des couples clé: valeur entre accolades. Réaffecter une clé existante remplace sa valeur au lieu de créer une deuxième occurrence. Ce petit programme modifie le montant d’une dépense :

expense = {"name": "lunch", "amount": 8000}
expense["amount"] = 9000
print(expense["amount"])

Il affiche 9000. La clé amount existe toujours une seule fois. Les clés textuelles distinguent la casse et les espaces : "food", "Food" et "food " sont des clés différentes. Les clés doivent être hachables ; les chaînes et les entiers conviennent, les listes ne conviennent pas.

L’ordre d’insertion est conservé, mais ce n’est pas un tri automatique par nom ou par montant. Pour imposer un ordre de présentation, exprimez le tri voulu. La référence des dictionnaires décrit les opérations disponibles et leur comportement.

Calculer des totaux par catégorie

Python 3 et sa bibliothèque standard suffisent. Enregistrez le programme complet suivant dans dicts.py, en UTF-8, dans un dossier d’exercice. Ouvrez le terminal dans ce dossier, activez l’environnement virtuel du projet et lancez python dicts.py. Sur macOS ou Ubuntu hors environnement virtuel, utilisez python3 si c’est le nom de votre interpréteur.

expenses = [("food", 8000), ("transport", 2500), ("food", 3500)]
totals = {}
for category, amount in expenses:
    totals[category] = totals.get(category, 0) + amount
for category, total in sorted(totals.items()):
    print(category, total)
print(totals.get("books", 0))

La sortie attendue est :

food 11500
transport 2500
0

Chaque tuple représente une catégorie et un montant dans une unité commune. food signifie « alimentation », transport « transport » et books « livres ». Ces étiquettes restent en anglais pour reproduire les résultats du programme ; elles ne sont pas traduites automatiquement par Python.

Au premier food, get renvoie le défaut 0, puis l’affectation crée la clé avec 8000. Au deuxième food, get retrouve 8000 : l’addition donne 11500, qui remplace le total précédent. transport reçoit 2500. Le tri de totals.items() ordonne ici les couples selon leurs clés, pas selon leurs montants.

La dernière ligne affiche 0 parce que books est absent et qu’un défaut a été demandé. Elle ne prouve pas qu’une catégorie books a été enregistrée avec un montant nul. Cette différence compte si vous devez distinguer « aucune donnée reçue » de « montant connu égal à zéro ».

Choisir une lecture obligatoire ou une valeur par défaut

totals["books"] lève une KeyError si la clé manque. totals.get("books", 0) renvoie zéro sans insérer la clé. Si la catégorie est obligatoire, vérifiez "books" in totals et signalez son absence au lieu de la masquer par un défaut. La valeur par défaut convient ici au début d’une addition, parce qu’un premier montant doit partir de zéro.

Une boucle sur le dictionnaire fournit les clés ; values() fournit les valeurs et items() les couples. Une copie ordinaire comme totals.copy() ne duplique que le dictionnaire extérieur. Si une valeur est une liste, elle peut rester partagée ; les principes de copie superficielle et d’objets partagés restent pertinents.

Un objet hachable doit fournir un hachage stable pendant sa durée de vie ; deux objets égaux doivent avoir le même hachage. Le glossaire Python sur le hachage définit ce contrat. Un tuple contenant une liste ne convient donc pas comme clé, même si son conteneur extérieur est immuable.

Quand ce cumul avec zéro se répète, defaultdict(int) peut simplifier l’écriture. Sa documentation dans collections précise toutefois une différence : un accès entre crochets à une clé absente peut la créer avec la fabrique prévue. Le comportement de get ne doit pas être confondu avec cet accès.

Tester les catégories et les changements de clés

  1. Remplacez seulement le montant 3500 de food par 4500. Le total food devient 12500, celui de transport reste 2500. Rétablissez 3500 pour retrouver la sortie initiale.
  2. Remplacez seulement le premier food par Food. Le programme affiche deux catégories distinctes : Food avec 8000 et food avec 3500, plus transport avec 2500. Rétablissez l’étiquette initiale.
  3. Ajoutez temporairement print("books" in totals) après la dernière ligne. Vous obtenez False : l’appel à get n’a pas ajouté la clé. Retirez cet affichage pour restaurer le programme.

Décidez d’une règle de normalisation des étiquettes avant de fusionner casse ou espaces. Une différence peut être une faute de saisie ou une distinction intentionnelle ; les méthodes de nettoyage ne peuvent pas décider cette règle métier à votre place.

Ajouter ou supprimer des clés pendant le parcours du même dictionnaire peut lever une RuntimeError. Rassemblez les clés à traiter dans une liste séparée avant les suppressions, ou construisez un nouveau dictionnaire. Si vous observez des catégories inattendues, inspectez d’abord les clés réelles et leur nombre avant de modifier le calcul des montants.