Mon Labo Python

Comment créer un dictionnaire imbriqué en python pour ses données

Comment créer un dictionnaire imbriqué en python pour ses données

Mon carnet de notes était ouvert à côté de la théière tiède, gribouillé de relevés météo bricolés pour trois collines du Puy-de-Dôme. Mes listes Python commençaient à ressembler à un tiroir à couverts sans séparateur, où les fourchettes se mélangent aux petites cuillères. Il fallait que je range tout ça proprement avant d'aller dormir.

Quand les listes plates deviennent un fouillis inextricable

Au début, quand on découvre la programmation, on a tendance à tout empiler dans de simples listes. J'avais créé une liste pour les températures de Clermont-Ferrand, une autre pour la vitesse des rafales vers le sommet du puy de Dôme, et encore une autre pour les dates de mes observations. Sur le papier, cela semblait fonctionner pour deux ou trois lignes de test. Mais dès que j'ai voulu croiser mes données pour savoir quel jour le vent soufflait fort alors qu'il faisait doux en ville, mon script est devenu un véritable casse-tête de boucles imbriquées et d'indices impossibles à aligner.

En suivant un module de ma formation sur les structures de données en langage Python, j'ai vu passer le concept des dictionnaires. Pas le gros pavé posé sur l'étagère du salon, mais cette structure qui associe une étiquette — une clé — à une valeur. Je connaissais déjà la version basique, un peu comme un carnet d'adresses. Seulement, mes données réelles ne sont jamais plates. Une ville ne possède pas juste une température ; elle a une altitude, un taux d'humidité, et plusieurs capteurs qui renvoient des chiffres différents selon l'heure.

L'écran bleuté qui éclaire la toile cirée de la cuisine et le ronronnement continu de la bouilloire qui refroidit formaient le décor habituel de mes soirées d'apprentissage. J'ai repoussé les exemples tout faits du cours, ceux avec des paniers de fruits ou des catalogues de livres imaginaires, pour essayer de modéliser directement mes propres observations météo locales. C'est là que l'idée d'un dictionnaire à l'intérieur d'un autre dictionnaire s'est imposée.

Mains au-dessus d'un clavier d'ordinateur à côté d'un carnet de notes manuscrites

Le grand plongeon : fabriquer un dictionnaire dans un dictionnaire

Lors d'une soirée pluvieuse de la fin septembre, je me suis enfin décidée à taper la syntaxe. L'idée générale est étonnamment visuelle : au lieu d'associer un mot à un nombre simple comme meteo = {'Clermont': 14}, on associe à notre clé externe un tout nouveau dictionnaire complet. Cela ressemble à des boîtes de rangement glissées dans un grand tiroir de commode.

Voici la structure de départ que j'ai fini par écrire après plusieurs ratures sur mon bloc-notes :

stations = {
    'Clermont-Ferrand': {
        'altitude': 358,
        'temperature': 14.2,
        'vent': 12
    },
    'Puy-de-Dome': {
        'altitude': 1465,
        'temperature': 6.8,
        'vent': 45
    }
}

Sur le coup, voir ces accolades s'emboîter proprement m'a donné une petite bouffée de satisfaction. Pour lire une information précise, la logique demande simplement d'enchaîner les clés. Pour savoir quelle brise soufflait au sommet, j'ai découvert qu'il fallait utiliser exactement 2 crochets consécutifs : le premier attrape la boîte extérieure, le second ouvre le compartiment intérieur, ce qui donne stations['Puy-de-Dome']['vent'].

Une petite précision historique que j'ai lue au détour de la documentation technique : depuis Python 3.7, l'ordre d'insertion des clés dans les dictionnaires est garanti par la spécification standard du langage. Pour une débutante comme moi, cela signifie simplement que lorsque j'affiche mon dictionnaire ou que je parcours mes villes, elles apparaissent toujours dans l'ordre où je les ai écrites, sans que Python ne vienne chambouler la disposition sans prévenir.

Mais évidemment, rien ne se passe jamais sans accroc dès qu'on essaie de modifier la boîte à la volée. J'ai voulu ajouter une station pour Royat sans l'avoir initialisée au préalable, en écrivant directement stations['Royat']['temperature'] = 11.5. La sanction a été immédiate. Mon curseur immobile devant trois lignes rouges de KeyError dans le terminal parce qu'un crochet fermait au mauvais endroit et que Python cherchait désespérément une étiquette 'Royat' qui n'existait tout simplement pas encore dans la mémoire de la machine.

Pour ajouter une sous-catégorie proprement sans faire planter le script, il m'a fallu apprendre à d'abord déclarer le sous-dictionnaire vide, ou vérifier son existence :

# Créer d'abord la boîte vide avant de remplir ses compartiments
stations['Royat'] = {}
stations['Royat']['altitude'] = 450
stations['Royat']['temperature'] = 11.5

Apprivoiser l'imbrication au quotidien : boucles et sécurité

Après une quinzaine de jours de pratique à jongler avec ces accolades, mon premier réflexe a été d'écrire des boucles pour explorer ces étages. Si vous avez déjà parcouru une liste simple, parcourir un dictionnaire imbriqué demande une petite gymnastique d'esprit. On utilise généralement la méthode .items() pour récupérer à la fois l'étiquette et son contenu :

for ville, donnees in stations.items():
    temp = donnees['temperature']
    alt = donnees['altitude']
    print(f"{ville} (alt. {alt}m) : {temp} degres")

C'est propre, lisible, et cela m'a rappelé le soulagement ressenti lors de mes essais pour utiliser la méthode split en python en soirée, quand un bloc de texte brut se découpe enfin en éléments exploitables. Mais un piège guette toujours les amateurs : que se passe-t-il si l'une des stations n'a pas de capteur de vent et ne possède donc pas cette clé ?

Si vous faites donnees['vent'] sur un dictionnaire incomplet, le script s'arrête net sur une redoutable erreur de clé manquante. Pour contourner ce blocage brutal au beau milieu d'une boucle, la méthode standard get() est devenue ma meilleure amie. Elle permet de demander poliment une valeur tout en prévoyant une issue de secours si la clé n'existe pas :

# Si 'vent' n'existe pas, Python renvoie 'Non mesure' au lieu de tout casser
vitesse_vent = donnees.get('vent', 'Non mesure')

Prendre l'habitude de tester la structure avec des petits print() réguliers avant d'écrire des extractions alambiquées m'a épargné bien des migraines tardives. Si vous hésitez encore sur la manière d'organiser vos conteneurs de base, jeter un œil à comment comprendre la différence entre liste et tuple en python simplement aide aussi à faire le tri dans ses outils.

Table de cuisine avec nappe cirée, tasse et ordinateur portable allumé le soir

Pourquoi j'ai fini par freiner : le piège des dictionnaires trop profonds

Je pensais avoir trouvé la solution universelle à tous mes soucis d'organisation de données. Alors, jeudi dernier après le dîner, j'ai voulu pousser l'expérience un peu plus loin. J'ai ajouté un sous-niveau pour les heures de relevé (matin, midi, soir), puis sous chaque heure, un autre sous-niveau pour séparer les valeurs brutes des moyennes corrigées.

Mon code s'est mis à ressembler à ceci :

releve = stations['Clermont-Ferrand']['horaires']['matin']['capteurs']['temperature']

C'est à cet instant précis que le charme s'est rompu. Une simple faute de frappe dans une chaîne de caractères — un 's' oublié à 'horaire' ou une majuscule mal placée — et tout s'écroulait silencieusement jusqu'à la prochaine exécution. Mon éditeur de texte ne me signalait aucune erreur, car pour lui, ces clés entre guillemets ne sont que du texte arbitraire, impossible à vérifier à l'avance.

Voici ce que cette soirée m'a appris : n'utilisez pas de dictionnaires imbriqués pour structurer vos données complexes. Dès que vous dépassez deux niveaux de profondeur, les dictionnaires deviennent un piège de maintenance infernal. On passe son temps à chercher comment s'appelait telle sous-clé, on invente des vérifications avec .get() à n'en plus finir pour éviter que le troisième étage ne s'effondre, et le code devient totalement illisible pour quiconque le relit deux semaines plus tard.

Sur les conseils avisés d'un collègue qui m'a vue pester contre mes crochets, j'ai commencé à regarder des alternatives plus solides offertes par Python, notamment les dataclasses et les namedtuples. Plutôt que de stocker mes mesures dans des sacs de texte sans contrôle, ces outils permettent de définir un véritable schéma avec des champs fixes (comme station.temperature au lieu de station['temperature']). Cela évite les fautes d'inattention, offre une auto-complétion salutaire dans l'éditeur, et empêche d'insérer n'importe quoi par accident.

Les dictionnaires imbriqués restent très pratiques pour lire un petit fichier de configuration ou pour manipuler rapidement des données reçues d'Internet au format JSON. Mais pour ranger mes propres données de travail, je préfère désormais poser des limites strictes. Deux étages, c'est utile. Trois étages, c'est déjà le début des ennuis.

Mon script météo tourne désormais sans planter sur le coin de ma table, même si je regarde encore d'un œil méfiant ces cascades d'accolades qui s'étirent sur mon écran. Il me reste encore à comprendre comment convertir proprement tout ce petit monde vers des formats tabulaires sans perdre mes sous-niveaux en route, mais ce sera un chantier pour un autre soir, quand la bouilloire sera pleine.

Articles connexes