NSI · 1ère Spécialité · Python

Les Dictionnaires en Python

Cours complet — Méthodes — Exercices progressifs — QCM interactif

01 — Introduction

Qu'est-ce qu'un dictionnaire ?

Un dictionnaire est une structure de données qui associe des clés à des valeurs. Plutôt que d'accéder à un élément par son indice numérique (comme dans une liste), on y accède par une clé significative.

📋 Définition
Un dictionnaire Python est une collection de paires clé : valeur, non ordonnée (avant Python 3.7) puis ordonnée par ordre d'insertion (depuis Python 3.7). Les clés sont uniques et immuables (chaînes, entiers, tuples). Les valeurs peuvent être de n'importe quel type.

Dictionnaire vs liste — quand utiliser quoi ?

📖 Dictionnaire — accès par clé
  • On connaît le nom de ce qu'on cherche
  • Les données ont des étiquettes significatives
  • Accès immédiat : eleve["note"]

Exemples : fiche élève, carnet de contacts, caractéristiques d'un objet.
📋 Liste — accès par indice
  • On connaît la position de l'élément
  • Données de même nature, en séquence
  • Accès par position : notes[2]

Exemples : notes de la classe, températures de la semaine, pixels d'une image.
Premier exemple
# Fiche d'un élève — dictionnaire
eleve = {
    "nom"    : "Dupont",
    "prenom" : "Alice",
    "age"    : 16,
    "classe" : "1NSI",
    "note"   : 17.5
}

print(eleve["nom"])    # 'Dupont'
print(eleve["note"])   # 17.5
print(type(eleve))     # <class 'dict'>
print(len(eleve))      # 5  (nombre de paires clé:valeur)
02 — Créer un dictionnaire

Créer et initialiser un dictionnaire

Méthode 1 — Littérale (accolades)

# Dictionnaire non vide
scores = {"Alice": 18, "Bob": 12, "Clara": 15}

# Dictionnaire vide
vide = {}
vide2 = dict()   # autre syntaxe

Méthode 2 — Constructeur dict()

# Avec des arguments nommés (clés = identifiants Python)
eleve = dict(nom="Alice", age=16, note=17)

# À partir d'une liste de tuples (clé, valeur)
paires = [("a", 1), ("b", 2), ("c", 3)]
d = dict(paires)   # {"a": 1, "b": 2, "c": 3}

# Avec zip() — associer deux listes
prenoms = ["Alice", "Bob", "Clara"]
notes   = [18, 12, 15]
scores  = dict(zip(prenoms, notes))
# {"Alice": 18, "Bob": 12, "Clara": 15}

Méthode 3 — dict.fromkeys()

# Initialiser toutes les clés avec la même valeur
matieres = ["Maths", "NSI", "Français"]
bulletins = dict.fromkeys(matieres, 0)
# {"Maths": 0, "NSI": 0, "Français": 0}
⚠ Les clés sont uniques
Si une clé est définie deux fois, la deuxième valeur écrase la première.
d = {"a": 1, "b": 2, "a": 99} → {"a": 99, "b": 2}
03 — Accès et modification

Accéder et modifier les données

Accès à une valeur

d = {"nom": "Alice", "age": 16, "note": 17}

# Méthode 1 — crochets (lève KeyError si clé absente)
print(d["nom"])     # "Alice"
# print(d["absent"])  → KeyError !

# Méthode 2 — get() (retourne None si absent, ou une valeur par défaut)
print(d.get("age"))           # 16
print(d.get("absent"))        # None
print(d.get("absent", 0))     # 0  (valeur par défaut)
💡 get() ou crochets ?
Utilise d["cle"] quand tu es sûr que la clé existe. Utilise d.get("cle", valeur_defaut) quand la clé peut être absente — c'est plus sûr et évite les KeyError.

Tester l'existence d'une clé

d = {"nom": "Alice", "age": 16}

# L'opérateur 'in' teste la présence d'une CLÉ (pas d'une valeur)
print("nom"  in d)   # True
print("note" in d)   # False
print("Alice" in d)  # False — "Alice" est une valeur, pas une clé !

# Tester une valeur
print("Alice" in d.values())  # True

Ajouter, modifier, supprimer

d = {"nom": "Alice", "age": 16}

# Ajouter une nouvelle paire clé:valeur
d["note"] = 17
print(d)  # {"nom": "Alice", "age": 16, "note": 17}

# Modifier une valeur existante
d["age"] = 17
print(d)  # {"nom": "Alice", "age": 17, "note": 17}

# Supprimer une clé avec del
del d["note"]
print(d)  # {"nom": "Alice", "age": 17}

# Supprimer et récupérer la valeur avec pop()
age = d.pop("age")
print(age)  # 17
print(d)    # {"nom": "Alice"}

# pop() avec valeur par défaut (évite KeyError si clé absente)
val = d.pop("absent", 0)   # retourne 0 sans erreur
04 — Méthodes à connaître

Méthodes et fonctions essentielles

len() → int
Retourne le nombre de paires clé:valeur.
len({"a":1,"b":2}) → 2
.keys() → vue
Retourne une vue de toutes les clés. Convertir avec list() si besoin.
d.keys() → dict_keys(['a','b'])
.values() → vue
Retourne une vue de toutes les valeurs.
d.values() → dict_values([1, 2])
.items() → vue
Retourne une vue des paires (clé, valeur) sous forme de tuples. Idéal pour les boucles.
d.items() → dict_items([('a',1),...])
.get(cle, défaut) → valeur
Retourne la valeur pour cle, ou défaut (None par défaut) si la clé est absente. Ne lève pas d'erreur.
d.get("x", 0) → 0
.pop(cle, défaut) → valeur
Supprime la clé et retourne sa valeur. Lève KeyError si la clé est absente et qu'aucun défaut n'est fourni.
d.pop("age") → 16
.update(d2) → None
Fusionne le dictionnaire d2 dans le dictionnaire. Les clés existantes sont écrasées, les nouvelles sont ajoutées.
d.update({"c":3,"a":99})
.copy() → dict
Retourne une copie superficielle du dictionnaire (indépendante pour les valeurs simples).
d2 = d.copy()
.setdefault(cle, val) → valeur
Retourne la valeur si la clé existe. Sinon, ajoute la clé avec val et la retourne. Utile pour initialiser sans écraser.
d.setdefault("score", 0)
.clear() → None
Vide le dictionnaire. La variable existe toujours mais pointe vers un dict vide.
d.clear() → d vaut {}

Tableau récapitulatif

OpérationSyntaxeRésultat / effet
Accès (sûr)d.get("cle", def)Valeur ou def si absent
Accès (direct)d["cle"]Valeur ou KeyError
Ajout / modificationd["cle"] = valModifie en place
Suppressiondel d["cle"]Supprime la clé
Supp. + retourd.pop("cle")Retourne la valeur supprimée
Tester une clé"cle" in dTrue / False
Toutes les clésd.keys()Vue des clés
Toutes les valeursd.values()Vue des valeurs
Toutes les pairesd.items()Vue de tuples (clé, valeur)
Fusiond.update(d2)Ajoute/écrase avec d2
Taillelen(d)Nombre de paires
05 — Parcours

Parcourir un dictionnaire

Parcours par clés (par défaut)

scores = {"Alice": 18, "Bob": 12, "Clara": 15}

# for ... in d  →  parcourt les CLÉS
for prenom in scores:
    print(prenom)            # Alice, Bob, Clara

# Identique à :
for prenom in scores.keys():
    print(prenom)

Parcours par valeurs

for note in scores.values():
    print(note)              # 18, 12, 15

Parcours par paires clé + valeur — le plus utile !

for prenom, note in scores.items():
    print(f"{prenom} a eu {note}/20")
# Alice a eu 18/20
# Bob a eu 12/20
# Clara a eu 15/20

Algorithmes classiques sur les dictionnaires

Somme, moyenne, maximum, comptage
scores = {"Alice": 18, "Bob": 12, "Clara": 15}

# ── Somme des valeurs ────────────────────────────
total = 0
for note in scores.values():
    total += note
print(total)   # 45   (ou : sum(scores.values()))

# ── Moyenne ──────────────────────────────────────
moy = sum(scores.values()) / len(scores)
print(moy)     # 15.0

# ── Clé du maximum ───────────────────────────────
def meilleur(d):
    cle_max = None
    val_max = None
    for cle, val in d.items():
        if val_max is None or val > val_max:
            cle_max, val_max = cle, val
    return cle_max

print(meilleur(scores))   # "Alice"
# Ou avec max() + key= :
print(max(scores, key=scores.get))   # "Alice"

# ── Filtrer (élèves avec note ≥ 15) ─────────────
admis = {p: n for p, n in scores.items() if n >= 15}
print(admis)   # {"Alice": 18, "Clara": 15}

# ── Compter (occurrences dans une liste) ─────────
lettres = ["a", "b", "a", "c", "b", "a"]
comptage = {}
for lettre in lettres:
    comptage[lettre] = comptage.get(lettre, 0) + 1
print(comptage)   # {"a": 3, "b": 2, "c": 1}
💡 Pattern comptage — à retenir !
d[cle] = d.get(cle, 0) + 1 est le pattern classique pour compter des occurrences avec un dictionnaire. Si la clé n'existe pas, get retourne 0, puis on ajoute 1. C'est l'équivalent d'un compteur automatique.
06 — Dictionnaires et listes

Combiner dictionnaires et listes

En pratique, on combine très souvent les deux structures : liste de dictionnaires, dictionnaire de listes, etc.

Liste de dictionnaires — tableau de données

# Chaque élève est un dictionnaire, la classe est une liste
classe = [
    {"nom": "Alice", "note": 18, "mention": "TB"},
    {"nom": "Bob",   "note": 12, "mention": "AB"},
    {"nom": "Clara", "note": 15, "mention": "B"},
]

# Accéder à la note de Bob
print(classe[1]["note"])   # 12

# Afficher tous les noms
for eleve in classe:
    print(eleve["nom"])      # Alice, Bob, Clara

# Calculer la moyenne de la classe
moy = sum(e["note"] for e in classe) / len(classe)
print(round(moy, 1))       # 15.0

# Élève avec la meilleure note
top = max(classe, key=lambda e: e["note"])
print(top["nom"])           # "Alice"

Dictionnaire de listes — regrouper par catégorie

# Notes par matière
notes_par_matiere = {
    "Maths"  : [14, 16, 11, 18],
    "NSI"    : [17, 15, 19, 13],
    "Anglais": [12, 10, 15, 14]
}

# Moyenne de NSI
n_nsi = notes_par_matiere["NSI"]
moy_nsi = sum(n_nsi) / len(n_nsi)
print(moy_nsi)   # 16.0

# Ajouter une note en NSI
notes_par_matiere["NSI"].append(20)

# Afficher toutes les moyennes
for matiere, notes in notes_par_matiere.items():
    moy = round(sum(notes) / len(notes), 1)
    print(f"{matiere} : {moy}/20")
07 — Compréhension de dictionnaire

Dictionnaires en compréhension

📐 Syntaxe
{clé_expr: val_expr for variable in iterable if condition}
La partie if condition est optionnelle.
# Carrés des entiers de 0 à 4
carres = {x: x**2 for x in range(5)}
# {0:0, 1:1, 2:4, 3:9, 4:16}

# Inverser un dictionnaire (clés ↔ valeurs)
d = {"a": 1, "b": 2, "c": 3}
inverse = {v: k for k, v in d.items()}
# {1: "a", 2: "b", 3: "c"}

# Filtrer : garder seulement les notes ≥ 15
scores = {"Alice": 18, "Bob": 12, "Clara": 15}
admis = {p: n for p, n in scores.items() if n >= 15}
# {"Alice": 18, "Clara": 15}

# Transformer : convertir les notes sur 20 en pourcentages
pct = {p: round(n * 5, 1) for p, n in scores.items()}
# {"Alice": 90.0, "Bob": 60.0, "Clara": 75.0}

# Construire depuis deux listes avec zip
prenoms = ["Alice", "Bob", "Clara"]
notes   = [18, 12, 15]
d = {p: n for p, n in zip(prenoms, notes)}
# {"Alice": 18, "Bob": 12, "Clara": 15}
08 — Exercices

Exercices progressifs

5 exercices de difficulté croissante. Réfléchis avant de consulter la correction !

⭐ Niveau 1 · Exercice 1
Manipulation de base

On dispose du dictionnaire suivant représentant un film :

film = {"titre": "Interstellar", "annee": 2014, "note": 8.6, "genre": "SF"}
  1. Afficher le titre du film.
  2. Afficher le nombre de clés du dictionnaire.
  3. Ajouter la clé "realisateur" avec la valeur "Nolan".
  4. Modifier la note à 9.0.
  5. Supprimer la clé "genre".
  6. Tester si la clé "acteurs" est présente, et afficher un message adapté.
  7. Afficher toutes les clés, puis toutes les valeurs.
▶ Voir la correction
film = {"titre": "Interstellar", "annee": 2014, "note": 8.6, "genre": "SF"}

print(film["titre"])                     # "Interstellar"
print(len(film))                          # 4
film["realisateur"] = "Nolan"
film["note"] = 9.0
del film["genre"]
if "acteurs" in film:
    print("La clé acteurs est présente")
else:
    print("La clé acteurs est absente")
print(list(film.keys()))                  # ['titre', 'annee', 'note', 'realisateur']
print(list(film.values()))               # ['Interstellar', 2014, 9.0, 'Nolan']
⭐ Niveau 1 · Exercice 2
Parcours et calculs

On dispose des scores d'une partie de jeu vidéo :

scores = {"Alice": 4200, "Bob": 3800, "Clara": 5100, "David": 2900}
  1. Écrire score_total(d) qui retourne la somme de tous les scores.
  2. Écrire score_moyen(d) qui retourne la moyenne arrondie à 1 décimale.
  3. Écrire meilleur_joueur(d) qui retourne le nom du joueur avec le score le plus élevé.
  4. Afficher tous les joueurs avec leur score, du plus élevé au plus bas.
▶ Indice

Pour la Q4, utiliser sorted(d.items(), key=lambda x: x[1], reverse=True). Pour le meilleur joueur : max(d, key=d.get).

▶ Voir la correction
def score_total(d):
    return sum(d.values())

def score_moyen(d):
    return round(sum(d.values()) / len(d), 1)

def meilleur_joueur(d):
    return max(d, key=d.get)

# Classement du meilleur au moins bon
classement = sorted(scores.items(), key=lambda x: x[1], reverse=True)
for rang, (nom, score) in enumerate(classement, 1):
    print(f"{rang}. {nom} : {score} pts")

print(score_total(scores))    # 16000
print(score_moyen(scores))    # 4000.0
print(meilleur_joueur(scores)) # "Clara"
⭐⭐ Niveau 2 · Exercice 3
Comptage et construction
  1. Écrire compter_lettres(texte) qui retourne un dictionnaire comptant le nombre d'apparitions de chaque lettre (ignorer les espaces, ne pas distinguer majuscules/minuscules).
  2. Écrire compter_mots(texte) qui retourne un dictionnaire comptant le nombre d'apparitions de chaque mot.
  3. Écrire lettre_plus_frequente(texte) qui retourne la lettre la plus fréquente.

Tester avec : "le chat mange le rat et le rat mange le chat"

▶ Indice

Utiliser le pattern d[x] = d.get(x, 0) + 1. Pour ignorer les espaces : if c != ' '. Pour les minuscules : texte.lower(). Pour les mots : texte.split().

▶ Voir la correction
def compter_lettres(texte):
    d = {}
    for c in texte.lower():
        if c != " ":
            d[c] = d.get(c, 0) + 1
    return d

def compter_mots(texte):
    d = {}
    for mot in texte.lower().split():
        d[mot] = d.get(mot, 0) + 1
    return d

def lettre_plus_frequente(texte):
    d = compter_lettres(texte)
    return max(d, key=d.get)

phrase = "le chat mange le rat et le rat mange le chat"
print(compter_mots(phrase))
# {"le": 4, "chat": 2, "mange": 2, "rat": 2, "et": 1}
print(lettre_plus_frequente(phrase))
# "e"  (la plus fréquente)
⭐⭐ Niveau 2 · Exercice 4
Liste de dictionnaires — Gestion d'un catalogue

On dispose d'un catalogue de livres :

livres = [
    {"titre": "Dune",        "auteur": "Herbert",  "annee": 1965, "note": 9.1},
    {"titre": "1984",        "auteur": "Orwell",   "annee": 1949, "note": 8.9},
    {"titre": "Fondation",  "auteur": "Asimov",   "annee": 1951, "note": 8.7},
    {"titre": "Neuromancer","auteur": "Gibson",   "annee": 1984, "note": 7.8},
]
  1. Écrire note_moyenne(livres) qui retourne la note moyenne.
  2. Écrire livres_par_decennie(livres) qui retourne un dictionnaire dont les clés sont les décennies (1940, 1950…) et les valeurs des listes de titres.
  3. Écrire chercher_par_auteur(livres, auteur) qui retourne la liste des titres écrits par cet auteur.
  4. Écrire trier_par_note(livres) qui retourne la liste triée par note décroissante.
▶ Indice

Pour les décennies : annee - annee % 10 donne 1965 → 1960. Utiliser le pattern d.setdefault(decennie, []).append(titre).

▶ Voir la correction
def note_moyenne(livres):
    return round(sum(l["note"] for l in livres) / len(livres), 2)

def livres_par_decennie(livres):
    d = {}
    for livre in livres:
        dec = livre["annee"] - livre["annee"] % 10
        d.setdefault(dec, []).append(livre["titre"])
    return d

def chercher_par_auteur(livres, auteur):
    return [l["titre"] for l in livres if l["auteur"] == auteur]

def trier_par_note(livres):
    return sorted(livres, key=lambda l: l["note"], reverse=True)

print(note_moyenne(livres))           # 8.62
print(livres_par_decennie(livres))
# {1960: ['Dune'], 1940: ['1984'], 1950: ['Fondation'], 1980: ['Neuromancer']}
print(chercher_par_auteur(livres, "Asimov"))  # ["Fondation"]
⭐⭐⭐ Niveau 3 · Exercice 5
Problème complet — Gestion d'un réseau social

On modélise un mini-réseau social. Chaque utilisateur est représenté par un dictionnaire :

reseau = {
    "Alice": {"age": 17, "amis": ["Bob", "Clara"],    "posts": 23},
    "Bob":   {"age": 18, "amis": ["Alice", "David"],   "posts": 7},
    "Clara": {"age": 16, "amis": ["Alice"],           "posts": 41},
    "David": {"age": 17, "amis": ["Bob", "Eva"],      "posts": 15},
    "Eva":   {"age": 19, "amis": ["David"],           "posts": 3},
}
  1. nb_amis(reseau, nom) : retourne le nombre d'amis d'un utilisateur.
  2. utilisateur_plus_actif(reseau) : retourne le nom de l'utilisateur avec le plus de posts.
  3. sont_amis(reseau, u1, u2) : retourne True si u1 et u2 sont mutuellement amis.
  4. amis_communs(reseau, u1, u2) : retourne la liste des amis communs à u1 et u2.
  5. statistiques(reseau) : retourne un dictionnaire avec "nb_utilisateurs", "total_posts", "age_moyen" (arrondi à 1 décimale), "utilisateur_plus_actif".
▶ Indice

Pour amis_communs : convertir les listes d'amis en ensembles (set()) et utiliser l'intersection &, puis reconvertir en liste. Pour sont_amis : vérifier dans les deux sens.

▶ Voir la correction
def nb_amis(reseau, nom):
    return len(reseau[nom]["amis"])

def utilisateur_plus_actif(reseau):
    return max(reseau, key=lambda u: reseau[u]["posts"])

def sont_amis(reseau, u1, u2):
    return (u2 in reseau[u1]["amis"] and
            u1 in reseau[u2]["amis"])

def amis_communs(reseau, u1, u2):
    amis1 = set(reseau[u1]["amis"])
    amis2 = set(reseau[u2]["amis"])
    return list(amis1 & amis2)

def statistiques(reseau):
    ages = [reseau[u]["age"] for u in reseau]
    return {
        "nb_utilisateurs"       : len(reseau),
        "total_posts"           : sum(reseau[u]["posts"] for u in reseau),
        "age_moyen"             : round(sum(ages) / len(ages), 1),
        "utilisateur_plus_actif": utilisateur_plus_actif(reseau),
    }

print(nb_amis(reseau, "Alice"))             # 2
print(utilisateur_plus_actif(reseau))         # "Clara"
print(sont_amis(reseau, "Alice", "Bob"))    # True
print(amis_communs(reseau, "Alice", "Bob")) # [] (aucun ami commun)
print(statistiques(reseau))
# {"nb_utilisateurs": 5, "total_posts": 89, "age_moyen": 17.4, "utilisateur_plus_actif": "Clara"}
09 — Checklist DST

Ce que tu dois maîtriser pour le DST

Assure-toi de cocher chaque point avant le jour J.

Syntaxe de base

Méthodes essentielles

Parcours et algorithmes

🚨 Erreurs classiques à éviter
  • ❌ d["cle_absente"] → KeyError ! Utiliser d.get("cle", defaut)
  • ❌ "Alice" in d teste les clés, pas les valeurs. Pour les valeurs : "Alice" in d.values()
  • ❌ Modifier un dictionnaire pendant qu'on le parcourt (faire une copie d'abord)
  • ❌ Confondre {} (dict vide) avec set() (ensemble vide). type({}) → dict
  • ❌ d.keys() n'est pas une liste : utiliser list(d.keys()) si besoin d'indexation
  • ❌ Oublier que les clés doivent être immuables (pas de liste comme clé)
10 — QCM

Quiz interactif — Les Dictionnaires en Python

Banque de 52 questions. Choisissez le nombre de questions et lancez le tirage.

Nombre de questions :