Exercice 1 : Les types construits : tuple, liste, dictionnaire
Une table de données se représente en Python par une liste de dictionnaires. Avant de la manipuler, il faut être au clair sur les trois types construits et sur ce qui les distingue vraiment : la mutabilité.
point = (3, 7)
couleurs = ['rouge', 'vert', 'bleu']
eleve = {'nom': 'Ada', 'classe': '1G3', 'moyenne': 15.5}
x, y = point
couleurs[1] = 'jaune'
eleve['moyenne'] = 16.0
eleve['option'] = 'NSI'- a) Donnez la valeur de x, de y, de couleurs et de eleve après l'exécution de ces huit lignes.
- b) La ligne point[0] = 5 provoque une erreur. Laquelle, et pourquoi ? Que faudrait-il écrire pour obtenir un point de coordonnées 5 et 7 ?
- c) Expliquez la différence entre un tuple et une liste, puis donnez deux situations où le tuple est le bon choix.
- d) On écrit d = {couleurs: 1}. Cela échoue. On écrit d = {point: 1}. Cela fonctionne. Expliquez la règle qui gouverne les clés d'un dictionnaire.
- e) Écrivez l'expression qui donne la liste des clés du dictionnaire eleve, puis celle qui donne la liste de ses valeurs, puis celle qui teste si la clé 'option' y figure. Quel est le coût de ce test, et pourquoi n'est-il pas celui d'un parcours ?
Voir la correction
Réponses
- a) x = 3, y = 7 ; liste et dictionnaire modifiés en place
- b) TypeError : tuple immuable
- c) Tuple pour enregistrement figé ou clé
- d) Clé hachable, donc immuable
- e) 'option' in eleve : coût constant
a) Le dépaquetage x, y = point donne x valant 3 et y valant 7. La liste couleurs devient ['rouge', 'jaune', 'bleu'], car l'affectation d'un élément modifie la liste EN PLACE. Le dictionnaire devient {'nom': 'Ada', 'classe': '1G3', 'moyenne': 16.0, 'option': 'NSI'} : la première affectation remplace la valeur d'une clé existante, la seconde ajoute une clé qui n'existait pas. Les deux s'écrivent de la même façon, ce qui est commode mais explique aussi qu'une faute de frappe sur un nom de clé crée silencieusement une clé de plus au lieu de signaler une erreur.
b) L'erreur est un TypeError, avec un message du genre « tuple object does not support item assignment ». Le tuple est IMMUABLE : une fois créé, aucun de ses éléments ne peut être remplacé. Pour obtenir un point de coordonnées 5 et 7, il faut construire un nouveau tuple, par exemple point = (5, point[1]) ou point = (5, 7). On ne modifie pas un tuple, on le remplace.
c) Une liste est muable, sa taille et son contenu peuvent changer après création ; un tuple est immuable, il est figé. Deux situations où le tuple s'impose. D'abord, pour représenter un ENREGISTREMENT dont les champs ne changent pas de nature, comme un couple de coordonnées ou une date : le lecteur du code sait alors qu'aucune ligne ne viendra le modifier. Ensuite, quand la valeur doit servir de CLÉ de dictionnaire ou d'élément d'ensemble, ce que la question d explique.
d) La règle est qu'une clé de dictionnaire doit être HACHABLE, c'est-à-dire qu'on doit pouvoir en calculer une empreinte numérique stable dans le temps. Un objet muable ne peut pas l'être : si l'on rangeait la liste couleurs à l'emplacement calculé d'après son contenu, puis qu'on modifiait ce contenu, l'objet se retrouverait rangé au mauvais endroit et deviendrait introuvable. Le tuple, immuable, n'a pas ce problème. C'est donc l'immuabilité qui autorise l'usage comme clé, et non une propriété arbitraire du langage.
e) Les clés s'obtiennent par list(eleve.keys()), les valeurs par list(eleve.values()), et le test par 'option' in eleve. Ce test a un coût CONSTANT, c'est-à-dire indépendant du nombre de clés, parce qu'un dictionnaire n'est pas parcouru : la clé est transformée en empreinte, et l'empreinte donne directement l'emplacement où regarder. C'est exactement l'inverse d'un test d'appartenance dans une liste, qui parcourt les éléments un par un et coûte donc proportionnellement à leur nombre. Cette différence est le principal argument pour représenter une ligne de table par un dictionnaire plutôt que par une liste.