Écrire renommer cle(d, ancienne, nouvelle)
Exercice d'entraînement · niveau 2 · NSI (première), chapitre 5 — Les dictionnaires · Construire et modifier
Énoncé
Écrire renommer_cle(d, ancienne, nouvelle). Deux préconditions sont nécessaires — lesquelles, et que se passerait-il sans elles ?
Corrigé
def renommer_cle(d, ancienne, nouvelle):
"""Renomme une cle EN PLACE.
Precondition : ancienne est presente, nouvelle est absente -- sinon on
ecraserait silencieusement une entree existante.
"""
assert ancienne in d, "cle absente : " + str(ancienne)
assert nouvelle not in d, "cle deja prise : " + str(nouvelle)
d[nouvelle] = d.pop(ancienne)
return d
Sans la première, d.pop(ancienne) lèverait KeyError — l'erreur arriverait quand même, mais sans dire laquelle des deux clés pose problème. Sans la seconde, le renommage détruirait l'entrée qui portait déjà le nouveau nom : le dictionnaire perdrait une entrée en silence, et len(d) diminuerait sans que rien ne le signale. C'est le défaut le plus grave des deux, parce qu'il ne produit aucune erreur.
pop plutôt que lire-puis-supprimer. d[nouvelle] = d.pop(ancienne) fait en une ligne ce que trois feraient : lire la valeur, l'installer sous le nouveau nom, effacer l'ancienne entrée. L'ordre compte — écrire del d[ancienne] avant d'avoir lu la valeur la perdrait.
Vérification.
d = {"lait": 1, "pain": 2}
assert renommer_cle(d, "lait", "lait demi-ecreme") == {"pain": 2,
"lait demi-ecreme": 1}
assert len(d) == 2
for cas in [("absente", "x"), ("pain", "pain")]:
try:
renommer_cle(dict(d), cas[0], cas[1])
assert False, cas
except AssertionError:
pass
Le second cas — renommer "pain" en "pain" — est celui qu'on oublie de tester, et c'est celui qui détruirait l'entré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.