Écrire fusion(d1, d2) renvoyant un nouveau dictionnaire contenant les…
Exercice de TD · niveau 2 · NSI (première), chapitre 5 — Les dictionnaires · Construire, lire, modifier
Énoncé
Écrire fusion(d1, d2) renvoyant un nouveau dictionnaire contenant les entrées des deux. Que décidez-vous pour une clé présente dans les deux ? Écrire cette décision dans la docstring, puis vérifier que d1 et d2 n'ont pas bougé.
Corrigé
def fusion(d1, d2):
"""Nouveau dictionnaire contenant les entrees de d1 et de d2.
Precondition : d1 et d2 sont des dictionnaires.
Postcondition : les cles du resultat sont exactement celles de d1 et d2
reunies ; pour une cle presente dans les deux, c'est la
valeur de d2 qui est retenue -- d2 ECRASE d1.
"""
resultat = {}
for cle, valeur in d1.items():
resultat[cle] = valeur
for cle, valeur in d2.items():
resultat[cle] = valeur
return resultat
La décision est arbitraire ; l'écrire ne l'est pas. Rien, dans l'énoncé, n'impose que d2 l'emporte : on aurait pu garder d1, ou refuser la fusion par une précondition, ou renvoyer une liste des deux valeurs. Ce qui n'est pas facultatif, c'est de dire ce qu'on a choisi. Une fonction dont la docstring se tait sur les clés communes oblige chaque lecteur à relire le code — et à le relire encore le mois suivant.
Pourquoi d2 écrase sans qu'on l'écrive nulle part. Aucune ligne du corps ne teste la présence d'une clé : c'est la règle du chapitre — « la même syntaxe crée et modifie » — qui fait tout le travail. La seconde boucle écrase les entrées déjà posées par la première, simplement parce qu'elle passe après. Le comportement vient de l'ordre des deux boucles, et c'est bien pour cela qu'il faut le documenter : il est invisible à la lecture.
Vérification.
a = {"pain": 2, "lait": 1}
b = {"lait": 3, "oeufs": 6}
assert fusion(a, b) == {"pain": 2, "lait": 3, "oeufs": 6}
assert fusion(b, a) == {"lait": 1, "oeufs": 6, "pain": 2}
assert a == {"pain": 2, "lait": 1} # a n'a pas bouge
assert fusion({}, {}) == {}
for _ in range(2000):
d1 = {random.randint(0, 9): random.randint(0, 9)
for _ in range(random.randint(0, 6))}
d2 = {random.randint(0, 9): random.randint(0, 9)
for _ in range(random.randint(0, 6))}
f = fusion(d1, d2)
assert set(f) == set(d1) | set(d2)
assert len(f) <= len(d1) + len(d2)
Les deux premiers assert ne sont pas redondants : ils vérifient que fusion(a, b) et fusion(b, a) diffèrent. Le troisième garde l'essentiel — la fonction ne modifie pas ses arguments. Les tirages contrôlent que le résultat a bien les clés des deux réunies, et au plus autant d'entrées que la somme des deux : l'inégalité est stricte dès qu'une clé est commune.
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.