15  Les dictionnaires

Les dictionnaires (dict) sont la deuxième structure fondamentale de Python après les listes. Là où une liste associe des indices (0, 1, 2…) à des valeurs, un dictionnaire associe des clés (souvent des chaînes) à des valeurs. C’est l’outil parfait pour représenter des données structurées : une personne, un produit, une configuration…

15.1 Qu’est-ce qu’un dictionnaire ?

Un dictionnaire est une collection de paires clé: valeur. On le crée avec des accolades {}.

personne = {
    "nom": "Alice",
    "age": 30,
    "ville": "Paris",
}
print(personne)
{'nom': 'Alice', 'age': 30, 'ville': 'Paris'}

On accède aux valeurs par leur clé, entre crochets (comme pour une liste, mais avec la clé au lieu de l’indice) :

print(personne["nom"])
print(personne["age"])
Alice
30

Caractéristiques clés :

  1. Collection de paires clé/valeur.
  2. Modifiable (mutable).
  3. Clés uniques : une clé existe en un seul exemplaire.
  4. Clés immuables : chaînes, nombres, tuples… mais pas listes ni dicts.
  5. Ordonné depuis Python 3.7 : l’ordre d’insertion est conservé.

Créer un dictionnaire vide

d1 = {}
d2 = dict()
print(d1, d2)
{} {}

Types de clés autorisés

# Clés chaînes (le plus courant)
d1 = {"a": 1, "b": 2}

# Clés entières
d2 = {1: "un", 2: "deux"}

# Clés tuples (si vous voulez des clés composites)
d3 = {("Alice", "Maths"): 15, ("Alice", "Physique"): 14}

# Mélange
d4 = {"nom": "Alice", 1: "un", (0, 0): "origine"}

print(d1)
print(d2)
print(d3)
print(d4)
{'a': 1, 'b': 2}
{1: 'un', 2: 'deux'}
{('Alice', 'Maths'): 15, ('Alice', 'Physique'): 14}
{'nom': 'Alice', 1: 'un', (0, 0): 'origine'}
# ❌ Clés listes : impossible (mutables)
d = {[1, 2]: "valeur"}
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[5], line 2
      1 # ❌ Clés listes : impossible (mutables)
----> 2 d = {[1, 2]: "valeur"}

TypeError: unhashable type: 'list'

15.2 Accéder aux valeurs

Accès par crochets

personne = {"nom": "Alice", "age": 30}
print(personne["nom"])
Alice

Si la clé n’existe pas : KeyError.

personne = {"nom": "Alice"}
print(personne["adresse"])
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[7], line 2
      1 personne = {"nom": "Alice"}
----> 2 print(personne["adresse"])

KeyError: 'adresse'

Accès sûr avec get()

La méthode get() renvoie None (ou une valeur par défaut) si la clé n’existe pas, sans erreur.

personne = {"nom": "Alice"}

print(personne.get("nom"))                   # "Alice"
print(personne.get("adresse"))               # None
print(personne.get("adresse", "inconnue"))   # "inconnue" (valeur par défaut)
Alice
None
inconnue
Crochets vs get() : quand choisir ?
  • Crochets d[cle] : quand vous êtes sûr que la clé existe (sinon KeyError).
  • d.get(cle) : quand la clé peut manquer et que vous voulez gérer ce cas.

Question TOSA fréquente : « Que renvoie d.get('x') si la clé n’existe pas ? » → None (pas d’erreur).

15.3 Ajouter, modifier, supprimer

Ajouter ou modifier

L’affectation sert à la fois à ajouter et à modifier :

personne = {"nom": "Alice", "age": 30}

# Ajouter une nouvelle clé
personne["ville"] = "Paris"

# Modifier une clé existante (même syntaxe)
personne["age"] = 31

print(personne)
{'nom': 'Alice', 'age': 31, 'ville': 'Paris'}

Supprimer

Méthode Effet
del d[cle] Supprime la clé (lève KeyError si absente)
d.pop(cle) Supprime et renvoie la valeur
d.pop(cle, default) Idem, sans erreur si absent (renvoie default)
d.clear() Vide tout le dictionnaire
personne = {"nom": "Alice", "age": 30, "ville": "Paris"}

del personne["age"]
print(personne)

valeur = personne.pop("ville")
print("Retirée :", valeur)
print("Reste :", personne)

personne.clear()
print(personne)
{'nom': 'Alice', 'ville': 'Paris'}
Retirée : Paris
Reste : {'nom': 'Alice'}
{}

Tester l’appartenance avec in

L’opérateur in teste la présence d’une clé (pas d’une valeur).

personne = {"nom": "Alice", "age": 30}

print("nom" in personne)      # True
print("Alice" in personne)    # False ! "Alice" est une valeur, pas une clé
print("age" in personne)      # True
True
False
True

Pour tester une valeur : valeur in d.values() (vu plus bas).

15.4 Méthodes principales

Parcourir les clés, valeurs ou paires

Méthode Renvoie
d.keys() Vue sur les clés
d.values() Vue sur les valeurs
d.items() Vue sur les paires (clé, valeur) (tuples)
personne = {"nom": "Alice", "age": 30, "ville": "Paris"}

print("Clés :", list(personne.keys()))
print("Valeurs :", list(personne.values()))
print("Items :", list(personne.items()))
Clés : ['nom', 'age', 'ville']
Valeurs : ['Alice', 30, 'Paris']
Items : [('nom', 'Alice'), ('age', 30), ('ville', 'Paris')]
Les « vues » ne sont pas des listes

d.keys(), d.values(), d.items() renvoient des vues dynamiques, pas des listes. Elles reflètent les modifications du dictionnaire en temps réel. Pour obtenir une vraie liste, on utilise list(d.keys()).

Autres méthodes utiles

Méthode Effet
d.update(autre_dict) Fusionne un autre dict (écrase les clés existantes)
d.setdefault(cle, val) Renvoie d[cle] si existe, sinon crée avec val
len(d) Nombre de paires
personne = {"nom": "Alice", "age": 30}

# update : fusion
personne.update({"ville": "Paris", "age": 31})  # "age" écrasé
print(personne)

# setdefault : crée si absent, sinon renvoie l'existant
couleur = personne.setdefault("couleur", "bleu")
print("Couleur ajoutée :", couleur)
print(personne)

# Si on refait setdefault avec une clé déjà là : pas d'écrasement
couleur = personne.setdefault("couleur", "rouge")
print("Couleur inchangée :", couleur)
{'nom': 'Alice', 'age': 31, 'ville': 'Paris'}
Couleur ajoutée : bleu
{'nom': 'Alice', 'age': 31, 'ville': 'Paris', 'couleur': 'bleu'}
Couleur inchangée : bleu

15.5 Parcourir un dictionnaire

Il y a plusieurs façons de parcourir un dictionnaire, chacune avec son usage.

Parcourir les clés (comportement par défaut)

personne = {"nom": "Alice", "age": 30, "ville": "Paris"}

for cle in personne:              # équivaut à for cle in personne.keys()
    print(cle)
nom
age
ville

Parcourir les valeurs

for valeur in personne.values():
    print(valeur)
Alice
30
Paris

Parcourir les paires (recommandé)

C’est la façon la plus courante et la plus utile :

for cle, valeur in personne.items():
    print(f"{cle}{valeur}")
nom → Alice
age → 30
ville → Paris

15.6 Dictionnaires imbriqués

On peut mettre un dictionnaire à l’intérieur d’un autre. Très utile pour des données structurées hiérarchiquement.

personnes = {
    "alice": {"age": 30, "ville": "Paris"},
    "bob": {"age": 25, "ville": "Lyon"},
    "charlie": {"age": 35, "ville": "Marseille"},
}

print(personnes["alice"])
print(personnes["alice"]["ville"])

# Ajouter une info à une personne existante
personnes["alice"]["email"] = "alice@example.com"
print(personnes["alice"])
{'age': 30, 'ville': 'Paris'}
Paris
{'age': 30, 'ville': 'Paris', 'email': 'alice@example.com'}
Le dictionnaire = structure de données reine en Python

On retrouve les dicts partout :

  • JSON (format de données sur le web) : c’est littéralement du dictionnaire Python.
  • Configuration d’applications.
  • Décomposition d’objets (un dict est souvent une alternative aux classes au niveau Basique).
  • Comptage d’occurrences : {"mot": 3, "autre": 1, ...}.
  • Index : {"nom" : objet, ...} pour accès O(1).

Maîtriser les dicts = moitié du chemin vers un Python idiomatique.

15.7 Les dictionnaires depuis Python 3.7 : ordre d’insertion conservé

Évolution importante

Depuis Python 3.7, les dictionnaires conservent l’ordre d’insertion. Ce n’était pas garanti avant. Aujourd’hui, vous pouvez compter dessus — c’est particulièrement utile pour la lisibilité et pour certains algorithmes.

d = {}
d["a"] = 1
d["c"] = 2
d["b"] = 3
print(d)   # {"a": 1, "c": 2, "b": 3} — ordre d'insertion préservé
{'a': 1, 'c': 2, 'b': 3}

🧩 Quiz 6.1 — Les dictionnaires

Question 1

Que renvoie d["x"] si d = {"a": 1, "b": 2} ?

  1. None
  2. 0
  3. KeyError
  4. False

c) KeyError — l’accès par crochets lève une erreur si la clé n’existe pas.

d = {"a": 1, "b": 2}
print(d["x"])
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[19], line 2
      1 d = {"a": 1, "b": 2}
----> 2 print(d["x"])

KeyError: 'x'

Pour un accès sûr, utilisez .get() :

d = {"a": 1, "b": 2}
print(d.get("x"))             # None
print(d.get("x", "défaut"))   # "défaut"
None
défaut

Question 2

Quelle clé est INVALIDE ?

  1. "nom"
  2. 42
  3. (1, 2)
  4. [1, 2]

d) [1, 2] — les listes sont mutables et ne peuvent pas être clés de dictionnaire. Seuls les objets immuables (chaînes, nombres, tuples de valeurs immuables) sont autorisés.

d = {[1, 2]: "valeur"}
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[21], line 1
----> 1 d = {[1, 2]: "valeur"}

TypeError: unhashable type: 'list'

Question 3

Que s’affiche-t-il ?

d = {"a": 1, "b": 2}
d["a"] = 10
d["c"] = 3
print(d)
  1. {"a": 1, "b": 2, "c": 3}
  2. {"a": 10, "b": 2, "c": 3}
  3. {"a": 10, "b": 2}
  4. Une erreur

b) {"a": 10, "b": 2, "c": 3} — l’affectation modifie la valeur existante pour "a" et ajoute une nouvelle paire pour "c".

d = {"a": 1, "b": 2}
d["a"] = 10
d["c"] = 3
print(d)
{'a': 10, 'b': 2, 'c': 3}

Question 4

Quelle méthode renvoie la liste des valeurs d’un dictionnaire ?

  1. d.keys()
  2. d.values()
  3. d.items()
  4. list(d)

b) d.values()keys() donne les clés, items() les paires, et list(d) est équivalent à list(d.keys()).

d = {"a": 1, "b": 2, "c": 3}
print(list(d.values()))
[1, 2, 3]

Question 5

Que teste "Alice" in {"nom": "Alice"} ?

  1. La présence de "Alice" comme clé → renvoie False
  2. La présence de "Alice" comme valeur → renvoie True
  3. L’existence du dictionnaire → renvoie True
  4. Une erreur

a) La présence de "Alice" comme clé → renvoie Falsein teste les clés par défaut sur un dictionnaire. Ici "Alice" est une valeur, pas une clé.

d = {"nom": "Alice"}
print("Alice" in d)             # False (pas une clé)
print("Alice" in d.values())    # True (c'est une valeur)
print("nom" in d)               # True (c'est une clé)
False
True
True

Question 6

Que s’affiche-t-il ?

d = {"a": 1, "b": 2}
for k, v in d.items():
    print(k, "→", v)
  1. Une erreur
  2. a → 1 puis b → 2
  3. 1 → a puis 2 → b
  4. ("a", 1) puis ("b", 2)

b) a → 1 puis b → 2items() renvoie des paires (clé, valeur) qu’on déballe dans k, v. C’est la forme la plus courante pour parcourir un dict.

d = {"a": 1, "b": 2}
for k, v in d.items():
    print(k, "→", v)
a → 1
b → 2

Question 7

Que vaut len(d) pour d = {"a": 1, "b": 2, "c": [3, 4, 5]} ?

  1. 3
  2. 5
  3. 6
  4. 7

a) 3len() sur un dictionnaire renvoie le nombre de paires (clés). Le fait qu’une valeur soit une liste n’y change rien.

d = {"a": 1, "b": 2, "c": [3, 4, 5]}
print(len(d))
3

Question 8

Que s’affiche-t-il ?

d = {"a": 1}
d.update({"a": 10, "b": 2})
print(d)
  1. {"a": 1, "b": 2}
  2. {"a": 10, "b": 2}
  3. {"a": [1, 10], "b": 2}
  4. Une erreur

b) {"a": 10, "b": 2}update() écrase les clés existantes avec les nouvelles valeurs et ajoute les clés nouvelles.

d = {"a": 1}
d.update({"a": 10, "b": 2})
print(d)
{'a': 10, 'b': 2}

✏️ Exercice 7.1 — Fiche personne

Créez un dictionnaire représentant une personne avec les clés nom, age, ville, puis :

  1. Affichez la ville.
  2. Ajoutez une clé email.
  3. Modifiez l’âge pour l’incrémenter de 1.
  4. Supprimez la ville.
  5. Affichez toutes les paires clé-valeur.
personne = {
    "nom": "Alice",
    "age": 30,
    "ville": "Paris",
}

# 1. Afficher la ville
...

# 2. Ajouter email
...

# 3. Incrémenter l'âge
...

# 4. Supprimer la ville
...

# 5. Afficher toutes les paires
...
personne = {
    "nom": "Alice",
    "age": 30,
    "ville": "Paris",
}

# 1. Afficher la ville
print("Ville :", personne["ville"])

# 2. Ajouter email
personne["email"] = "alice@example.com"

# 3. Incrémenter l'âge
personne["age"] += 1

# 4. Supprimer la ville
del personne["ville"]

# 5. Afficher toutes les paires
for cle, valeur in personne.items():
    print(f"{cle} : {valeur}")
Ville : Paris
nom : Alice
age : 31
email : alice@example.com

✏️ Exercice 7.2 — Compter les occurrences

Écrivez une fonction compter(texte) qui renvoie un dictionnaire indiquant le nombre d’occurrences de chaque lettre dans texte (on ignore la casse).

Exemple : compter("Banana"){"b": 1, "a": 3, "n": 2}.

def compter(texte):
    occurrences = {}
    # Parcourir chaque caractère, mettre en minuscule, compter
    ...
    return occurrences

print(compter("Banana"))
print(compter("anticonstitutionnellement"))
def compter(texte):
    occurrences = {}
    for c in texte.lower():
        if c in occurrences:
            occurrences[c] += 1
        else:
            occurrences[c] = 1
    return occurrences

print(compter("Banana"))
print(compter("anticonstitutionnellement"))
{'b': 1, 'a': 3, 'n': 2}
{'a': 1, 'n': 5, 't': 5, 'i': 3, 'c': 1, 'o': 2, 's': 1, 'u': 1, 'e': 3, 'l': 2, 'm': 1}

Plus concise : on utilise get(c, 0) pour démarrer à 0 si la clé est absente.

def compter_v2(texte):
    occurrences = {}
    for c in texte.lower():
        occurrences[c] = occurrences.get(c, 0) + 1
    return occurrences

print(compter_v2("Banana"))
{'b': 1, 'a': 3, 'n': 2}

La bibliothèque standard Python propose une classe dédiée :

from collections import Counter

print(Counter("Banana".lower()))
Counter({'a': 3, 'n': 2, 'b': 1})

On verra les modules en détail au chapitre 12.


✏️ Exercice 7.3 — Inverser un dictionnaire

Écrivez une fonction qui, à partir d’un dictionnaire, renvoie un nouveau dictionnaire où clés et valeurs sont échangées.

Exemple : {"a": 1, "b": 2}{1: "a", 2: "b"}.

def inverser(d):
    ...
    return ...

print(inverser({"a": 1, "b": 2, "c": 3}))
def inverser(d):
    resultat = {}
    for cle, valeur in d.items():
        resultat[valeur] = cle
    return resultat

print(inverser({"a": 1, "b": 2, "c": 3}))
{1: 'a', 2: 'b', 3: 'c'}

Attention : si plusieurs clés ont la même valeur dans l’original, on perd des données en inversant, car les clés du nouveau dict doivent être uniques :

d = {"a": 1, "b": 1, "c": 2}
print(inverser(d))
# Résultat : {1: "b", 2: "c"} — "a" est perdu !
{1: 'b', 2: 'c'}

Vu plus tard, mais voici un aperçu :

def inverser_v2(d):
    return {v: k for k, v in d.items()}

print(inverser_v2({"a": 1, "b": 2, "c": 3}))
{1: 'a', 2: 'b', 3: 'c'}

À retenir

Points clés du chapitre
  1. Un dictionnaire associe des clés uniques et immuables à des valeurs de tout type.
  2. Accès : d[cle] (erreur si absent) ou d.get(cle, defaut) (sûr).
  3. Ajout/modification : d[cle] = valeur (même syntaxe).
  4. Suppression : del d[cle], d.pop(cle), d.clear().
  5. Parcours : for k, v in d.items(): (forme idiomatique).
  6. in teste la présence d’une clé (pas d’une valeur).
  7. keys(), values(), items() renvoient des vues dynamiques, pas des listes.
  8. Les clés ne peuvent PAS être des listes (mutables), mais peuvent être des tuples.
  9. Depuis Python 3.7, l’ordre d’insertion est conservé.

← Chapitre précédent : Les tuplesChapitre suivant : Les ensembles →