Comment parcourir un dic Python sans erreurs de débutant ?

Un dic Python itéré par défaut sur ses clés : écrire for k in d: équivaut strictement à for k in d.keys(). Appeler keys() explicitement n’apporte rien en performance ni en lisibilité, sauf quand on veut signaler une intention au relecteur. Partir de ce constat permet déjà d’éliminer une couche de code inutile que nous retrouvons dans la majorité des revues de code junior.

KeyError en dic Python : bug de modélisation ou simple clé absente

Toute tentative d’accès par d[key] sur une clé inexistante lève un KeyError. La question que trop peu de développeurs se posent : cette absence est-elle attendue ou révèle-t-elle un problème structurel dans le dictionnaire lui-même ?

Un KeyError « normal » survient quand la clé peut légitimement manquer. Exemple : un champ optionnel dans une réponse d’API JSON. Le dictionnaire est correctement construit, mais certaines entrées n’existent pas à chaque appel. Ici, get() est la réponse adaptée parce qu’on accepte une valeur par défaut.

Un KeyError symptôme de bug, en revanche, signale que le dictionnaire ne contient pas ce qu’il devrait contenir. Typiquement : une clé mal orthographiée, un pipeline de transformation qui a supprimé ou renommé un champ en amont, ou une logique de peuplement incomplète. Masquer ce type d’erreur avec get() repousse le problème plus loin dans l’exécution, où il devient beaucoup plus coûteux à diagnostiquer.

Utiliser get() sur une clé qui devrait toujours exister est un anti-pattern. Si la clé est contractuelle (schéma fixe, données validées en amont), laissez le KeyError remonter. Il signale immédiatement une rupture de contrat.

Développeur Python travaillant sur un dictionnaire Python dans un espace de coworking moderne avec code visible à l'écran

Choisir entre get(), in et setdefault() sur un dic Python

Nous recommandons de raisonner en trois cas distincts, chacun associé à un outil précis.

Clé optionnelle avec valeur de repli

d.get("timeout", 30) renvoie la valeur si la clé existe, sinon le second argument. Pas de levée d’exception, pas de branchement conditionnel. C’est la forme la plus concise pour les champs facultatifs.

Clé dont l’absence déclenche un traitement spécifique

Quand l’absence de clé doit provoquer une action (journalisation, alerte, création d’une entrée), le test if key in d: suivi d’un bloc explicite reste plus lisible qu’un enchaînement get() + vérification du retour. Tester avec in avant d’agir rend l’intention visible dans le code.

Clé à initialiser au premier accès

setdefault() insère la valeur par défaut dans le dictionnaire si la clé n’existe pas encore, puis la renvoie. Le cas d’usage classique : construire un dictionnaire de listes à la volée.

Attention au piège documenté : setdefault(key, []) crée bien une nouvelle liste à chaque appel (contrairement à dict.fromkeys(keys, []) qui partage la même référence entre toutes les clés). Mais defaultdict(list) du module collections fait le même travail de façon plus idiomatique quand le pattern se répète sur tout le dictionnaire.

  • get() : lecture seule, clé optionnelle, valeur de repli fournie.
  • in : branchement conditionnel explicite, traitement différent selon la présence ou l’absence.
  • setdefault() : initialisation paresseuse d’une valeur dans le dictionnaire lui-même, utile pour les agrégations.

Parcourir un dictionnaire Python avec items() sans modifier sa taille

for k, v in d.items() reste la forme canonique pour accéder aux paires clé-valeur. Le piège majeur pendant l’itération concerne la modification de la taille du dictionnaire.

Ajouter ou supprimer une clé à l’intérieur d’une boucle for k in d: provoque un RuntimeError (ou un comportement imprévisible sur les versions plus anciennes). Le moteur CPython détecte que la taille du dictionnaire a changé entre deux étapes de l’itérateur.

Deux stratégies fiables pour contourner le problème :

  • Itérer sur une copie figée des clés avec for k in list(d):, ce qui permet de supprimer ou d’ajouter des entrées dans d en toute sécurité.
  • Construire un nouveau dictionnaire par compréhension : {k: v for k, v in d.items() if condition(v)}. Plus lisible quand on filtre un dictionnaire entier.
  • Utiliser popitem() en boucle while d: pour vider un dictionnaire de manière destructive, sans itérateur.

Ne jamais muter la taille d’un dic pendant son itération : c’est la règle que la plupart des tutoriels mentionnent, mais que nous voyons encore transgressée en production, souvent masquée dans des fonctions utilitaires.

Clés hashables et pièges de dict.fromkeys() en Python

Contrainte de hashabilité des clés

Un objet mutable (liste, set, autre dict) ne peut pas servir de clé. Tenter d[[1, 2]] = "valeur" lève immédiatement un TypeError. Si vous avez besoin d’une séquence comme clé, convertissez-la en tuple.

Cette contrainte découle directement de l’implémentation par table de hachage. Seuls les objets dont le hash ne change pas pendant leur durée de vie peuvent servir de clé de dictionnaire.

Le piège de dict.fromkeys() avec une valeur mutable

dict.fromkeys(["a", "b", "c"], []) crée trois clés qui pointent toutes vers la même liste en mémoire. Modifier d["a"] modifie aussi d["b"] et d["c"]. La correction consiste à utiliser une compréhension de dictionnaire : {k: [] for k in ["a", "b", "c"]}, qui instancie une liste distincte pour chaque clé.

Étudiant en informatique analysant un dictionnaire Python sur son ordinateur portable dans une bibliothèque universitaire

Le parcours d’un dic Python devient prévisible dès qu’on applique une discipline simple : laisser remonter les KeyError sur les clés contractuelles, réserver get() aux champs réellement optionnels, et ne jamais altérer la taille du dictionnaire pendant une itération. Ces trois réflexes couvrent la grande majorité des bugs que nous observons lors des revues de code.

Quelques actus

Le Samsung Galaxy A90 serait la première d’une caméra jamais vue auparavant dans Samsung

Samsung ne s'arrête pas. Après avoir présenté le nouveau Samsung Galaxy S10 et lancé les Samsung Galaxy A30

Pourquoi choisir UX Design ?

Le monde du numérique impose l’utilisation du processus de l’UX Design. Tous les webdesigners doivent prendre cet élément