Adloun

Un carnet de notes associe à chaque élève la liste de ses notes

Exercice d'entraînement · niveau 2 · NSI (première), chapitre 5 — Les dictionnaires · Construire et modifier

Énoncé

Un carnet de notes associe à chaque élève la liste de ses notes. Écrire ajouter_note(carnet, eleve, note), qui crée l'entrée si l'élève est nouveau, puis moyennes(carnet). Essayer ensuite dict.fromkeys(["a", "b"], []) et expliquer ce qui se passe.

Corrigé


def ajouter_note(carnet, eleve, note):
    """Ajoute une note a un eleve, en creant son entree s'il est nouveau.

    Precondition  : 0 <= note <= 20.
    Postcondition : le nombre total de notes du carnet a augmente de 1.
    """
    assert 0 <= note <= 20, "note hors bareme"
    avant = sum(len(v) for v in carnet.values())
    if eleve in carnet:
        carnet[eleve].append(note)
    else:
        carnet[eleve] = [note]
    assert sum(len(v) for v in carnet.values()) == avant + 1
    return carnet


def moyennes(carnet):
    return {eleve: sum(notes) / len(notes)
            for eleve, notes in carnet.items() if notes}

Le piège de fromkeys.


piege = dict.fromkeys(["a", "b"], [])
piege["a"].append(1)
assert piege == {"a": [1], "b": [1]}     # UNE seule liste pour DEUX cles

fromkeys ne construit pas une liste par clé : il pose la même liste partout. C'est le partage de références du chapitre 4, et il est ici invisible — le dictionnaire a l'air normal jusqu'au premier append. La version avec else: carnet[eleve] = [note] crée une liste neuve à chaque élève, et c'est précisément pour cela qu'elle est correcte.

Le if notes dans moyennes. Une liste vide donnerait ZeroDivisionError. Le filtre écarte l'élève sans note plutôt que de faire tomber la fonction — c'est une décision à documenter, l'autre étant de refuser le carnet par une précondition.

Vérification.


carnet = {}
ajouter_note(carnet, "Nour", 14)
ajouter_note(carnet, "Yanis", 8)
ajouter_note(carnet, "Nour", 16)
assert carnet == {"Nour": [14, 16], "Yanis": [8]}
assert moyennes(carnet) == {"Nour": 15.0, "Yanis": 8.0}

try:
    ajouter_note(carnet, "Nour", 21)
    assert False
except AssertionError as e:
    assert "bareme" in str(e)

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.