Type associatif : dict
Relecture nécessaire
Ce chapitre a besoin d'une relecture. C'est ok de s'y attaquer.
Dans le TP répertoire des deux chapitres précédents, on a voulu associer par paire le nom d'un d'un contact et son adresse mail, pour pouvoir facilement retrouver l'adresse mail à partir du nom. On a dû implémenter des fonctions de recherche, d'ajout et de modifications spécialisées.
Python propose un type, dict
, ou dictionnaire, spécialisé dans la gestion d'associations par paires.
Construction
Quand on recherche un contact, on veut trouver son adresse mail à partir de son nom. On dit que le nom est la clé qui identifie l'adresse mail, et que l'adresse mail est la valeur identifiée.
On construit un dictionnaire en utilisant des accolades {}
.
On peut spécifier des paires sous la forme cle:valeur
, séparées par des virgules.
d = {"Alex Emple":"alexemple@unmail.fr",
"Daryl Ustration":"dust@autremail.fr",
"Clara Perçu":"thumbnail@mail.fr"}
Présence d'une clé
On peut tester si une clé est présente dans le dictionnaire avec le mot clé in
.
Accès à une valeur
On accède à la valeur associée à une clé en utilisant l'opérateur []
avec la syntaxe dictionnaire[cle]
.
affiche
Si on essaie d'accéder à une valeur et que la clé demandée n'existe pas, une erreur KeyError
est levée :
affiche :
Exercice
Implantez la fonction suivante :
def afficher_valeur(d, c):
"""d un dictionnaire
c une chaîne
si c est une clé de d, affiche la valeur associée à c dans d
sinon, affiche "clé non trouvée"
>>> afficher_valeur({}, "a")
clé non trouvée
>>> afficher_valeur({"a":"b","c":"d:"}, "a")
b
>>> afficher_valeur({"a":"b","c":"d:"}, "e")
clé non trouvée
"""
pass
Utilisez l'opérateur in
pour tester si la clé est présente dans le dictionnaire.
Utilisez l'opérateur []
pour accéder à la valeur associée à la clé.
Vous aurez probablement besoin d'un if ... else
.
def afficher_valeur(d, c):
"""d un dictionnaire
c une chaîne
si c est une clé de d, affiche la valeur associée à c dans d
sinon, affiche "clé non trouvée"
>>> afficher_valeur({}, "a")
clé non trouvée
>>> afficher_valeur({"a":"b","c":"d:"}, "a")
b
>>> afficher_valeur({"a":"b","c":"d:"}, "e")
clé non trouvée
"""
if c in d:
print(d[c])
else:
print("clé non trouvée")
Ajout et modification d'une valeur
L'opérateur []
utilisé avec la syntaxe suivante permet à la fois d'ajouter et de modifier des valeurs dans le dictionnaire.
Si cle
n'est pas dans dictionnaire
, alors la paire clé:valeur
est ajoutée au dictionnaire.
Affiche
Si cle
est présente dans le dictionnaire, alors sa valeur associée devient valeur
.
Affiche
Exercice
Implantez la fonction suivante :
def paires_vers_dict(liste):
"""liste une list de tuples (str,str)
retourne un dict où les paires de liste sont stockées sous forme clé:valeur.
Si une clé est trouvée deux fois, alors c'est la
dernière valeur correspondante qui est ajoutée.
>>> paires_vers_dict([])
{}
>>> paires_vers_dict([("a","b"), ("c","d")])
{'a': 'b', 'c': 'd'}
>>> paires_vers_dict([("a","b"), ("c","d"), ("a","e")])
{'a': 'e', 'c': 'd'}
"""
pass
def paires_vers_dict(liste):
"""liste une list de tuples (str,str)
retourne un dict où les paires de liste sont stockées sous forme clé:valeur.
Si une clé est trouvée deux fois, alors c'est la
dernière valeur correspondante qui est ajoutée.
>>> paires_vers_dict([])
{}
>>> paires_vers_dict([("a","b"), ("c","d")])
{'a': 'b', 'c': 'd'}
>>> paires_vers_dict([("a","b"), ("c","d"), ("a","e")])
{'a': 'e', 'c': 'd'}
"""
d = {}
for e in liste:
d[e[0]] = e[1]
return d
Parcours
Le dictionnaire a deux méthodes, keys
et values
qui retournent respectivement les clés et les valeurs.
affiche
On peut parcourir ces valeurs de retour de ces méthodes avec une boucle for
.
affiche
A noter qu'on peut utiliser for ... in ...
directement avec un dict
. Dans ce cas là, ce sont les clés qui sont parcourues. On peut également utiliser l'élément clé pour accéder à la valeur correspondante.
affiche
Exercice
Implantez la fonction suivante :
Vous pouvez utiliser l'opérateur in
sur les clés et valeurs obtenues avec les méthodes keys
et values
:
affiche
def cles_diff_vals(d):
"""d un dict
return True si aucune clé de d n'est valeur de d,
False sinon
>>> cles_diff_vals({})
True
>>> cles_diff_vals({'a':'b', 'c':'d'})
True
>>> cles_diff_vals({'a':'a', 'c':'d'})
False
>>> cles_diff_vals({'a':'b', 'b':'d'})
False
"""
for k in d:
if k in d.values():
return False
return True
Type des clés
Nous avons pour le moment utilisé des chaines comme clés et valeurs, mais le type dict
est moins restrictif.
Le type dict
autorise, entre autres, à créer des clés de types entiers, chaînes, flottants, booleen, None
, et tuples contenant les six types précédents.
Dans un même dict
, les clés ne sont pas nécessairement du même type. Toutefois, pour une meilleure lisibilité et simplicité du code, on se restreindra à créer et manipuler des dict
dont toutes les clés sont du même type.
Type des valeurs
Les valeurs dans un dictionnaire peuvent être de n'importe quel type, et même de types différents.
Sauf dans une exception que nous verrons en fin de chapitre, nous n'utiliserons que des dictionnaires où toutes les clés ont le même type, et toutes les valeurs ont le même type. Par exemple pour lister les notes en NSI des élèves:
Propriétés
Les clés retounées par la méthode keys()
sont dans l'ordre de leur insertion.
Les valeurs retournées par la méthode values()
sont dans l'ordre des clés correspondantes.
d = {1:2,3:4,5:6,7:8,9:10}
print(d.keys())
print(d.values())
d[1] = 5
print(d.keys())
print(d.values())
Affiche
dict_keys([1, 3, 5, 7, 9])
dict_values([2, 4, 6, 8, 10])
dict_keys([1, 3, 5, 7, 9])
dict_values([5, 4, 6, 8, 10])
Exercice
Cet exercice est relativement difficile, prenez donc votre temps pour le faire.
Implantez la fonction suivante :
Il vous faudra sans doute utiliser une liste itermédiaire pour stocker les clées en ordre inverse.
N'hésitez pas à consulter les exercices du chapitre précédent pour savoir comment on inverse une liste.
def inverse(d):
"""d un dictionnaire
retourne un dictionnaire qui contient les mêmes éléments
que d, mais avec les clés en ordre inverse
>>> inverse({"a":"b", "c":"d", "e":"f", "g":"h"})
{'g': 'h', 'e': 'f', 'c': 'd', 'a': 'b'}
>>> inverse({})
{}
"""
cles = []
for k in d:
cles.insert(0, k)
d2 = {}
for c in cles:
d2[c] = d[c]
return d2
Les dicts, au même titre que les lists, dont mutables.
affiche
Il convient donc d'être prudent lors de leur manipulation.
Structurer les données
On a vu que les list pouvaient être utiles pour manipuler beaucoup de données avec peu de variables.
On veut aussi parfois grouper et manipuler des données de types différents comme un tout. Jusqu'à présent, on a utilisé soit des variables séparées, soit un tuple.
Par exemple, pour représenter un contact.
Si l'on représente le contact avec plusieurs variables :
C'est compliqué à lire et on doit à chaque fois gérer toutes les variables.
Si on représente le contact par un tuple :
Comme l'accès aux éléments se fait à l'aide d'un entier, on a parfois du mal à voir ce que l'on fait si l'on a oublié l'organisation du tuple...
Utiliser un dict avec des clés de type chaîne résouds les deux problèmes à la fois:
Ici, une seule variable à manipuler, et l'accès à un élément est clair :
Cette structuration est la seule exception pour laquelle on acceptera de faire des dict avec des valeurs de types différents. A noter que les clés seront en revanches toutes des chaînes.
Exercice
Proposez une fonction addition
, qui permet d'additionner deux vecteurs représentés par des variables séparées, et qui retourne un vecteur sous forme de deux valeurs séparées. Utilisez-la pour additionner les vecteurs \((0, 4)\) et \((5,3)\)
Pour rappel, avec \(u = (u_x, u_y)\) et \(v = v_x, v_y)\) deux vecteurs en deux dimensions, on a :
Si vous n'y arrivez pas, cherchez un peu mais n'attendez pas trop pour regarder l'aide, puis la solution.
Une fonction Python peut retourner plusieurs valeurs, avec la syntaxe suivante :
Les valeurs sont en réalité emballées (packed en anglais) sous formes d'un tuple.
affiche
On peut déballer (unpack en anglais) les valeurs avec la syntaxe suivante :
Par exemple :
affiche
Proposez une fonction addition
et utilisez-la pour additionner les vecteurs \((0, 4)\) et \((5,3)\), pour les deux autres représentations proposées partie 1.