NSI (première) · Chapitre 5 · Exercice de TD
Écrire fusion(d1, d2) renvoyant un nouveau dictionnaire contenant les…
Les dictionnaires · Construire, lire, modifier · niveau 2
É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.
100 % gratuit
Essaie le suivant avec le tuteur
- L'exercice suivant avec le tuteur, sans compte : il guide pas à pas, sans donner la réponse
- 16 autres exercices corrigés dans ce chapitre, et 20 à chercher avec le tuteur
- Le podcast et la vidéo du chapitre et la correction filmée du TD : 2 minutes sans compte
Sans compte : le cours, 2 minutes de podcast et de vidéo et un exercice avec le tuteur. Pour tout le reste : inscription gratuite en 30 secondes, sans carte bancaire.