T2.3 Dictionnaires⚓︎
Jusqu'à présent, nous avons rencontré deux types de conteneurs (ou ensemble d'éléments) : les listes et les tuples. Ces deux types ont en commun le repérage de leurs éléments par un indice, qui est un nombre entier. Ces deux types sont ordonnés, on les appelle des séquences. L'indice est la clé qui permet d'accéder à un élément de l'ensemble.
Prenons comme exemple un autre ensemble d'éléments: les numéros de téléphone sauvegardés dans l'application « Contacts » de votre smartphone. Ces numéros ne sont pas ordonnés, et ne sont pas repérables par un indice, mais (en général) par un nom.
Grosso modo, le contenu de votre application « Contacts » est un ensemble d'associations nom: numéro
. En Informatique, on parle de tableau associatif ou de p-uplet nommé: un ensemble de (p) valeurs appelées par un descripteur autre qu'un indice.
En Python, on représentera ces p-uplets nommés par des dictionnaires.
2.3.1 Définition d'un dictionnaire, clés et valeurs⚓︎
Le type dict
>>> contacts = {"pap": '0155551010', "bénédicte": '0516526600', "christophe": '0545974500'}
-
Un dictionnaire (type
dict
) est une donnée composite qui n'est pas ordonnée (à la différence des listes !). Il fonctionne par un système declé: valeur
. -
Les clés, comme les valeurs, peuvent être de types différents.
-
Un dictionnaire est délimité par des accolades, les associations
clé: valeur
séparées par des espaces. -
On accède à une valeur par sa clé :
>>> contacts["pap"]
'0155551010'
Méthodes keys
et values
On peut lister les clés d'un dictionnaires:
>>> contacts.keys()
dict_keys(['pap', 'bénédicte', 'christophe'])
>>> contacts.values()
dict_values(['0155551010', '0516526600', '0545974500'])
Ajout/modification/suppression d'éléments
Pour modifier une valeur associée à une clé, on réaffecte la nouvelle valeur :
>>> contacts["pap"] = '0605040302'
>>> contacts
{'pap': '0605040302', 'bénédicte': '0516526600', 'christophe': '0545974500'}
clé: valeur
au dictionnaire:
>>> contacts["xavier"] = '0545387000'
>>> contacts
{'pap': '0605040302', 'bénédicte': '0516526600', 'christophe': '0545974500', 'xavier': '0545387000'}
La suppression d'une clé (et donc de sa valeur) se fait par le mot-clé del
:
>>> del contacts["pap"]
>>> contacts
{'bénédicte': '0516526600', 'christophe': '0545974500', 'xavier': '0545387000'}
2.3.2 Méthodes sur les dictionnaires⚓︎
Parcours d'un dictionnaire
On utilise comme pour les listes une boucle for
avec l'opérateur in
. Cet opérateur in
peut également tester l'appartenance d'une clé à un dictionnaire, hors d'un for
.
On parcourt par défaut sur les clés:
>>> for nom in contacts:
... print(nom)
bénédicte
christophe
xavier
>>> for nom in contacts:
... print(f"le numéro de {nom} est {contacts[nom]}")
...
le numéro de bénédicte est 0516526600
le numéro de christophe est 0545974500
le numéro de xavier est 0545387000
Il serait équivalent de faire for nom in contacts.keys()
.
On peut également parcourir le dictionnaire sur les valeurs, mais sans possibilité alors de récupérer la clé à partir de la valeur (puisque plusieurs clés peuvent avoir la même valeur).
On utilisera pour cela:
>>> for v in contacts.values():
... print(v)
...
0516526600
0545974500
0545387000
Il peut être utile de parcourir à la fois sur les clés et sur les valeurs, c'est à dire sur l'élément complet clé: valeur
du dictionnaire, notamment si on souhaite récupérer la clé associée à une valeur donnée.
1 2 3 4 5 6 |
|
Création d'un dictionnaire vide et construction de dictionnaire
Comme les listes, il est très fréquent qu'on ait besoin de construire le dictionnaire par ajouts successifs en partant d'un dictionnaire vide.
On peut créer un dictionnaire vide de deux façons: {}
ou dict()
:
>>> dico = {}
>>> dico = dict()
>>> chiffres = ['zéro', 'un', 'deux', 'trois', 'quatre', 'cinq', 'six', 'sept', 'huit', 'neuf']
>>> for c in chiffres:
... dico[c] = len(c)
...
>>> dico
{'zéro': 4, 'un': 2, 'deux': 4, 'trois': 5, 'quatre': 6, 'cinq': 4, 'six': 3, 'sept': 4, 'huit': 4, 'neuf': 4}
On peut bien évidemment créer un dictionnaire en compréhension (hors-programme). On peut résumer le code précédent en:
dico = {c: len(c) for c in chiffres}
Gaspard's corner
Pour récupérer les clés d'un dictionnaire en fonction de leur valeur, il n'y a pas d'autre moyen que de parcourir le dictionnaire et de sélectionner les clés dont la valeur est celle cherchée.
Dans le dictionnaire dico
de l'exemple précédent, si on cherche les clés dont la valeur est égale à 4 par exemple:
1 2 3 4 |
|
>>> liste
['zéro', 'deux', 'cinq', 'sept', 'huit', 'neuf']
Mieux, on écrit une fonction qui prend en paramètre un dictionnaire et une valeur (entière par exemple) à chercher, ainsi que quelques tests:
1 2 3 4 5 6 7 8 9 10 11 |
|
Puisqu'on a créé une liste par ajout successifs dans une liste vide en parcourant un iterable (le dictionnaire dico
), on peut également la créer en compréhension...
1 |
|
Et la fonction deviet tout simplement:
1 2 |
|
2.3.3 Bilan⚓︎
En résumé
dico = dict()
crée un dictionnaire vide appelédico
,dico[cle] = contenu
met la valeurcontenu
pour la clécle
dans le dictionnairedico
,dico[cle]
renvoie la valeur associée à la clécle
dans le dictionnairedico
,cle in dico
renvoie un booléen indiquant si la clécle
est présente dans le dictionnairedico
.len(dico)
renvoie le nombre de clés d'un dictionnaire.for cle in dico:
permet d'itérer sur les clés d'un dictionnaire.for valeur in dico.values():
permet d'itérer sur les valeurs d'un dictionnaire.for cle, valeur in dico.items():
permet d'itérer sur les clés et les valeurs d'un dictionnaire.
2.3.4 Exercices⚓︎
Exercice 1
On considère le contenu de mon dressing, représenté par un dictionnaire:
dressing = {"pantalons": 3, "pulls": 4, "tee-shirts": 8}
- J'ai oublié mes 5 chemises... Ajoutez-les au dictionnaire
dressing
. - Écrire une fonction (ou plutôt une procédure, pas de return)
ajout(habit)
qui prend en paramètre un type d'habit et qui augmente son nombre de 1 dans le dictionnaire. - Améliorer la fonction pour qu'elle crée une nouvelle entrée si le type d'habit n'existe pas comme clé.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Exercice 2
On considère la liste suivante :
lst = ['5717', '1133', '5545', '4031', '6398', '2734', '3070', '1346', '7849', '7288', '7587', '6217', '8240', '5733', '6466', '7972', '7341', '6616', '5061', '2441', '2571', '4496', '4831', '5395', '8584', '3033', '6266', '2452', '6909', '3021', '5404', '3799', '5053', '8096', '2488', '8519', '6896', '7300', '5914', '7464', '5068', '1386', '9898', '8313', '1072', '1441', '7333', '5691', '6987', '5255']
Quel est le chiffre qui revient le plus fréquemment dans cette liste ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Exercice 3
On modélise des informations (nom, taille et poids) sur des Pokémons de la façon suivante:
exemple_pokemons = {
'Bulbizarre': (70, 7),
'Herbizarre': (100, 13),
'Abo': (200, 7),
'Jungko': (170, 52)
}
Bulbizarre
est un pokémon qui mesure 70 cm et pèse 7 kg.
- Ajouer le pokémon
Goupix
qui mesure 60 cm et pèse 10 kg. - Compléter la fonction
plus_grand
qui prend en paramètre un dictionnaire et qui renvoie un tuple contenant le nom du pokemon le plus grand et sa taille.
def plus_grand(pokemons: dict) -> tuple:
nom_plus_grand = ''
taille_max = 0
for in pokemons. :
if > taille_max:
nom_plus_grand =
taille_max =
return
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Exercice 4
Reprendre l'exercice «Le lion de Némée» (T2.1 exercice 7) et construire un dictionnaire dont les clés sont les noms des divinités et les valeurs leur «valeur» selon l'énoncé.
Il suffit de transformer la dernière ligne du programme où l'on créait une liste en compréhension par un dictionnaire créé également en compréhension:
valeurs_divinites = {d: valeur_mot(d) for d in divinites}
Exercice 5
Voici un dictionnaire dates
dont les clés sont des prénoms au format str
et les valeurs des dates de naissance au format tuple
.
dates = {
"Alan": (23, 6, 1912),
"Grace": (9, 12, 1906),
"Linus": (28, 12, 1969),
"Guido": (31, 1, 1956),
"Ada": (10, 12, 1815),
"Tim": (8, 6, 1955),
"Dennis": (9, 9, 1941),
"Hedy": (9, 11, 1914),
"Steve": (24, 2, 1955)
}
-
Ajouter les deux entrées suivantes: Margaret, née le 17 août 1936 et John, né le 28 décembre 1903.
-
Écrire une fonction
calendrier
qui prend en paramètre un dictionnaire constitué d'entréesnom: (jour, mois, année)
commedates
et qui renvoie un dictionnaire dont les clés sont les mois de l'année et les valeurs les listes des noms nés ce mois-là. Par exemple,calendrier(dates)
doit renvoyer un dictionnaire contenant l'entrée"juin": ["Alan", "Tim"]
. -
Écrire une fonction
plus_jeune
qui renvoie le nom de la personne la plus jeune du dictionnaire.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
Exercice 6
Voici un dictionnaire Python:
1 |
|
À l'aide d'un parcours du dictionnaire, créer le dictionnaire «inversé», c'est-à-dire en échangeant clés et valeurs.
1 2 3 |
|
Ou en compréhension:
1 |
|
Exercice 7
Ci-dessous, un célèbre texte a été écrit en code morse. Décodez le!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
|
Pour coder un texte en morse, on a besoin d'un dictionnaire de correspondance entre les lettres (majuscules) et leurs codes en morse.
Par exemple:
1 |
|
Ensuite il faut séparer la chaîne de caractères fournie sur les espaces pour obtenir la liste des codes: on utilise la méthode split
(voir ici).
Et enfin, en parcourant cette liste, on construit une nouvelle chaîne de caractères contenant le message décodé (variable accumulatrice).
1 2 3 4 5 6 |
|
Exercice 8
L’ARN contient le codage des protéines, composées de chaines d’acides aminés.
Le dictionnaire ci-dessous donne les correspondances entre les codons, des séquences d’ARN constitués de trois nucléotides, et les acides aminés.
La séquence AUG, par exemple, correspond à la méthionine, notée M.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Écrire une fonction traduction
qui traduit une chaine d’ARN en protéine. On suppose que la longueur
de la chaine d’ARN est un multiple de trois. Ainsi, traduction('UUCAGUGGG')
renverra 'FSG'
.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Exercice 9 (Épreuve pratique)
Écrire une fonction min_et_max
qui prend en paramètre un tableau de nombres tab
non vide, et qui renvoie la plus petite et la plus grande valeur du tableau sous la
forme d’un dictionnaire à deux clés min
et max
.
Les tableaux seront représentés sous forme de liste Python.
L’utilisation des fonctions natives min
, max
et sorted
, ainsi que la méthode sort
n’est pas autorisée.
Exemples :
>>> min_et_max([0, 1, 4, 2, -2, 9, 3, 1, 7, 1])
{'min': -2, 'max': 9}
>>> min_et_max([0, 1, 2, 3])
{'min': 0, 'max': 3}
>>> min_et_max([3])
{'min': 3, 'max': 3}
>>> min_et_max([1, 3, 2, 1, 3])
{'min': 1, 'max': 3}
>>> min_et_max([-1, -1, -1, -1, -1])
{'min': -1, 'max': -1}
Comme dans l'énoncé on annonce que le paramètre tab
est non vide, on peut prendre l'élément d'indice 0 comme valeur par défaut pour le minimum et le maximum.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Exercice 10 (BAC) : Jour suivant au format (jour, j, m, a)
On dispose des listes jours
, mois
et duree_mois
suivants :
jours = ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"]
mois = [
"janvier", "février", "mars", "avril",
"mai", "juin", "juillet", "aout",
"septembre", "octobre", "novembre", "décembre",
]
duree_mois = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
Pour un indice
i
de 0 à 11,mois[i]
etduree_mois[i]
indiquent le nom et la durée du mois d'indicei
. On considèrera donc dans cet exercice que tous les mois de février durent 28 jours.
-
a. À partir de la liste
jours
, comment obtenir l'élément"lundi"
?b. Que renvoie l'instruction
jours[18 % 7]
? -
On rappelle que
jours.index(element)
renvoie l'indice deelement
dans la listejours
.Par exemple,
jours.index("mercredi")
renvoie3
.Le nom du jour actuel est stocké dans une variable
nom_jour
(par exemple :nom_jour = "mardi"
).Recopier et compléter l'instruction suivante permettant d'obtenir l'indice du jour de la semaine
n
jours plus tard :indice_jour = (jours.index( ... ) + ...) % ...
-
a. À partir de la liste
mois
, comment obtenir le nombre de jours du mois de mars ?b. Les mois sont numérotés de 1 pour janvier à 12 pour décembre. Sachant que le numéro du mois actuel est stocké dans une variable
numero_mois
, écrire le code permettant d'obtenir le nom du mois qu'il serax
mois plus tard à partir de la listemois
.Par exemple :
- Avec
numero_mois = 4
etx = 5
, on doit obtenir"septembre"
. - Avec
numero_mois = 8
etx = 4
, on doit obtenir"décembre"
. - Avec
numero_mois = 10
etx = 3
, on doit obtenir"janvier"
.
Il est important d'enlever 1 au numéro, pour travailler avec l'indice qui commence à zéro.
- Avec
-
On définit une date comme un tuple :
(nom_jour, numero_jour, numero_mois, annee)
a. Par exemple, pour stocker la date du samedi 21 octobre 1995, on exécute
date = ("samedi", 21, 10, 1995)
. On peut alors extraire les champs de valeurs avecnom_jour, numero_jour, numero_mois, annee = date
. Que renvoie alors l'instructionmois[numero_mois - 1]
?b. Écrire une fonction
jour_suivant
qui prend en paramètre unedate
sous forme de tuple et qui renvoie un tuple désignant ladate
du lendemain.Par exemple
>>> jour_suivant(("samedi", 21, 10, 1995)) ("dimanche", 22, 10, 1995) >>> jour_suivant(("mardi", 31, 10, 1995)) ("mercredi", 1, 11, 1995)
Rappel : on ne tient pas compte des années bissextiles et on considère que le mois de février comporte toujours 28 jours.