Accès rapide :
La vidéo
Présentation du type dict
Instanciation d'un dictionnaire
Vérifier la présence ou non d'une association dans un dictionnaire
Ajouter des valeurs dans un dictionnaire
Modifier des valeurs dans un dictionnaire
Supprimer des valeurs d'un dictionnaire
Parcourir un dictionnaire
Les « Dict Comprehensions » (ou dictionnaire en compréhension, en français)
Compléments sur la manipulation de vos dictionnaires
Quelques fonctions applicables aux dictionnaires
Quelques méthodes de la classe dict
Quelques opérateurs de la classe dict
Typage de vos dictionnaires
Travaux pratiques
Les énoncés
Les corrections
Cette vidéo vous montre comment utiliser des dictionnaires (des tables associatives de type clé/valeur).
La classe dict
(contraction de dictionnary) permet la manipulation de tableaux
associatifs : on y associe une valeur à une clé. Les valeurs d'un dictionnaire ne sont donc pas stockées de manière séquentielle : pour accéder à une valeur
on utilise sa clé, plutôt de sa position. Les clés peuvent être de différentes natures (chaînes de caractères, numériques, dates...) et il en va de même
pour les valeurs.
dict
de Python.
Pour définir un dictionnaire, il faut utiliser une paire d'accolade, comme pour un set
.
Mais au lieu d'y stocker une séquence de valeurs, il faudra y définir des paires clé/valeur.
Commençons par définir un dictionnaire vide.
>>> empty_dict = {} >>> type(empty_dict) <class 'dict'> >>> len(empty_dict) 0 >>>
L'exemple suivant permet de définir un dictionnaire associant des noms de mois avec le nombre de jours contenu dans le mois. Nous ne considérerons pas le cas des années bissextiles : le mois de février contiendra donc 28 jours.
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30}
>>> len(months)
4
>>> months["mars"]
31
>>> months["truc"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'truc'
>>>
KeyError
sera produite.
Une autre possibilité pour accéder à une donnée d'un dictionnaire consiste à utiliser la méthode
a_dict.get(key)
.
La différence avec l'opérateur []
, vu dans l'exemple précédent, c'est qu'en cas de clé non existante, la valeur None
vous sera retournée plutôt qu'une exception. En voici un exemple.
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30}
>>> months.get("janvier")
31
>>> months.get("brumaire") # La valeur None est retournée (elle ne s'affiche pas).
>>> months.get("brumaire") is None
True
>>> months["brumaire"] # Une exception est déclenchée
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'brumaire'
>>>
a_dict.get(key)
>>> months = {"janvier": 31, "février": 28, "mars": 31, True: "Oui ca marche"} >>> len(months) 5 >>> months {'janvier': 31, 'février': 28, 'mars': 31, True: 'Oui ca marche'} >>> months["janvier"] 31 >>> months[True] 'Oui ca marche' >>>
Voici un autre exemple qui associe des dates à des listes de tâches à effectuer.
Pour avoir accès au type date
, il nous faut préalablement le charger à partir
du module (un fichier de code) datetime
.
>>> from datetime import date >>> tasks = { ... date(2022, 3, 26): ["Apprendre Python", "Manger", "Dormir"], ... date(2022, 3, 27): ["Poursuivre l'apprentissage de Python", "..."], ... date(2022, 3, 28): ["Se reposer un peu", "Dormir"] ... } >>> for task in tasks[date(2022, 3, 26)]: ... print(task) ... Apprendre Python Manger Dormir >>>
Vous pouvez savoir si une association est présente dans un dictionnaire, ou non, en utilisant l'opérateur in
.
Par défaut, l'opérateur teste la présence d'une clé dans la collection, mais vous pouvez le spécifier explicitement en indiquant la collection
dico.keys()
.
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30} >>> "février" in months True >>> "février" in months.keys() True >>> "brumaire" in months False >>>
A contrario, vous pouvez vérifier si une information n'est pas présente dans la collection avec l'opérateur not in
.
Voici des exemples d'utilisation.
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30} >>> "février" not in months False >>> "février" not in months.keys() False >>> "brumaire" not in months True >>>
Comme nous venons de le voir, par défaut, nous testons la présence d'une clé dans le dictionnaire.
Mais il est aussi possible de tester la présence d'une valeur : dans ce cas, il faudra explicitement utiliser la collection dico.values()
.
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30} >>> 31 in months # Ici on teste une clé et non une valeur. False >>> 31 in months.values() True >>> 32 in months.values() False >>>
Un dictionnaire est modifiable (comme une liste, par exemple) et vous pouvez donc, à tout moment, ajouter, modifier ou supprimer une association dans cette
collection. Pour ajouter une nouvelle valeur à un dictionnaire, nous devons passer par l'opérateur []
pour associer la valeur à sa clé.
>>> from datetime import date >>> tasks = { ... date(2022, 3, 26): ["Apprendre Python", "Manger", "Dormir"], ... date(2022, 3, 27): ["Poursuivre l'apprentissage de Python", "..."] ... } >>> # Ajout d'une nouvelle liste dans le dictionnaire >>> tasks[date(2022, 3, 28)] = ["Se reposer un peu", "Dormir"] >>> # On accède à cette nouvelle donnée >>> for task in tasks[date(2022, 3, 28)]: ... print(task) ... Se reposer un peu Dormir >>>
Comme nous venons de le signaler, il est possible de modifier la valeur associée à une clé donnée : voici un exemple qui change le nombre de jours du mois de février 2020 étant donné qu'il s'agissait d'une année bissextile.
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30} >>> year = 2020 >>> months["février"] = 29 # Modification de la valeur associé à la clé "février" >>> months {'janvier': 31, 'février': 29, 'mars': 31, 'avril': 30} >>> months["février"] 29 >>>
Un dictionnaire étant une structure de données modifiable, il est possible d'y retirer une (ou plusieurs) association(s) clé/valeur. Plusieurs possibilités vous sont offertes pour arriver à cet objectif en fonction que vous souhaitiez récupérer la valeur supprimer ou non.
Pour supprimer, mais aussi récupérer, une valeur d'un dictionnaire, il faut utiliser la méthode
pop
. Voici un exemple d'utilisation de cette méthode.
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30, "brumaire": 30} >>> months {'janvier': 31, 'février': 28, 'mars': 31, 'avril': 30, 'brumaire': 30} >>> value = months.pop("brumaire") >>> value 30 >>> months {'janvier': 31, 'février': 28, 'mars': 31, 'avril': 30} >>>
Si vous souhaitiez simplement supprimer une association clé/valeur (sans récupérer de valeur en sortie), otpez plutôt pour l'opérateur del
.
Voici un exemple d'utilisation de cet opérateur.
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30, "brumaire": 30} >>> del months["brumaire"] >>> months {'janvier': 31, 'février': 28, 'mars': 31, 'avril': 30} >>>
del
.>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30}
>>> del months["brumaire"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'brumaire'
>>>
Si vous souhaitez supprimer toutes les associations clé/valeur présentes dans un dictionnaire, vous pouvez aussi invoquer la méthode
clear
.
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30} >>> len(months) 4 >>> months {'janvier': 31, 'février': 28, 'mars': 31, 'avril': 30} >>> months.clear() >>> len(months) 0 >>> months {} >>>
Comme pour les autres collections, il est possible d'utiliser l'instruction for
pour parcourir un dictionnaire.
Mais comme un dictionnaire stocke des paires clé/valeur, plusieurs variations sont possibles lors de son parcours.
Par défaut, l'instruction for
permet de parcourir les clés d'un dictionnaire et non pas ses valeurs.
Voici un premier exemple de parcours des clés d'un dictionnaire.
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30} >>> for key in months: ... print(key) ... janvier février mars avril >>>
Vous pouvez aussi explicitement signifier que vous voulez parcourir les clés du dictionnaire, en effectuant la boucle la collection
a_dict.keys()
. Voici un exemple de code montrant cette possibilité.
Comme vous le constaterez, les affichages seront bien les mêmes qu'avec l'exemple précédent.
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30} >>> for key in months.keys(): ... print(key) ... janvier février mars avril >>>
Maintenant, vous pouvez aussi indiquer que vous souhaitez parcourir les valeurs du dictionnaire.
Pour ce faire, il faudra lancer l'instruction for
sur la collection
a_dict.values()
.
Voici un nouvel exemple de code montrant cette possibilité.
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30} >>> for key in months.values(): ... print(key) ... 31 28 31 30 >>>
Si vous souhaitez, à la fois, parcourir les clés et les valeurs, vous pouvez utiliser la méthode
a_dict.items()
.
Cette dernière renvoie une collection de tuples : chaque tuple sera constitué d'une clé et de sa valeur.
Voici un exemple d'utilisation.
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30} >>> for pair in months.items(): ... print(pair) ... ('janvier', 31) ('février', 28) ('mars', 31) ('avril', 30) >>>
a_dict.items()
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30} >>> for key, value in months.items(): ... print(key, "=>", value) ... janvier => 31 février => 28 mars => 31 avril => 30 >>>
a_dict.items()
A l'instar des listes en compréhention et des set en compréhention, il est possible de définir le contenu d'un dictionnaire par un algorithme. Imaginons que nous ayons une liste de langages de programmation. Vous pouvez alors construire un dictionnaire associant un langage avec le nombre de lettres qui constitue son nom, en parcourant les valeurs de la liste d'origine. Voici un exemple de code.
>>> raw_data = ["C", "C++", "Python", "Perl", "Java", "Visual Basic"] >>> data = {lang:len(lang) for lang in raw_data} >>> type(data) <class 'dict'> >>> data {'C': 1, 'C++': 3, 'Python': 6, 'Perl': 4, 'Java': 4, 'Visual Basic': 12} >>> data["Python"] 6 >>>
lang:len(lang)
où lang
et un des éléments de la liste
et len(lang)
la taille de la chaîne de caractères.
Voici un nouvel exemple de code ou l'on produit un dictionnaire à partir d'informations stockées dans un autre dictionnaire.
>>> initial = {x:x ** 2 for x in range(10)} >>> initial {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81} >>> final = {-x:x2 for x, x2 in initial.items()} >>> final {0: 0, -1: 1, -2: 4, -3: 9, -4: 16, -5: 25, -6: 36, -7: 49, -8: 64, -9: 81} >>>
initial.items()
qu'on déballe ensuite dans deux variables
x
et x2
. Au final, on régénère un dictionnaire quasi identique dans le lequel on inverse la valeur de x
.
Il existe de nombreuses fonctions applicables aux dictionnaires Python. Nous pouvons notamment citer :
len
: cette fonction permet de calculer la taille d'un dictionnaire
(mais nous l'avions déjà présentée avec les autres types de collections). En fait, c'est le nombre d'associations clé/valeur qui sera retourné.
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30} >>> len(months) 4 >>>
sorted
: cette fonction renvoie une liste triée des clés ou des valeurs
constitutives de votre dictionnaire.
>>> months = {"janvier": 31, "février": 28, "mars": 31, "avril": 30} >>> key_list = sorted(months) >>> key_list ['avril', 'février', 'janvier', 'mars'] >>> value_list = sorted(months.values()) >>> value_list [28, 30, 31, 31] >>>
Vous vous en doutez, la classe dict
expose aussi de nombreuses méthodes
bien utiles. En voici quelques-unes : vous pouvez cliquer sur le nom de la méthode pour en obtenir un descriptif plus détaillé.
Méthode | Description |
---|---|
clear |
Supprime toutes les données du dictionnaire. |
copy |
Duplique (shallow copy) un dictionnaire. |
fromkeys |
Permet de créer un nouveau dictionnaire à partir d'un jeu de clés. |
get |
Permet de retrouver une donnée du dictionnaire à partir de sa clé. |
items |
Renvoie l'ensemble des paires clé/valeur, sous forme d'une collection de tuples. |
keys |
Renvoie l'ensemble de clés du dictionnaire. |
pop |
Permet de supprimer et de retourner une donnée du dictionnaire à partir de sa clé. |
popitem |
Supprime une association du dictionnaire (en mode LIFO) et vous la renvoie sous forme d'un tuple. |
setdefault |
Insert une nouvelle entrée dans le dictionnaire, si la clé n'existe, et renvoie la valeur associée à la clé. |
update |
Fusionne dans le dictionnaire courant les entrées présente dans un autre dictionnaire. |
values |
Renvoie l'ensemble de clés du dictionnaire. |
Des opérateurs sont aussi supportés par la classe dict
.
On retrouve, bien entendu l'opérateur in
et l'opérateur not in
.
Nous avons aussi déjà vu l'opérateur del
, pour supprimer une donnée (et sa clé) du dictionnaire.
Mais je voulais aussi attirer votre attention sur l'opérateur d'union |
qui permet de fusionner deux dictionnaires de manière similaire à la
méthode update
. En voici un exemple.
>>> d1 = {"a": 1, "b": 2} >>> d2 = {"c": 3, "d": 4, "b": 22} >>> d1 | d2 {'a': 1, 'b': 22, 'c': 3, 'd': 4} >>>
|
Une autre manière d'arriver au même résultat consiste à mettre à plat le contenu de dictionnaires déjà existant dans le dictionnaire en cours
de construction. La mise à plat se fait via l'opérateur **
placé devant le dictionnaire à traiter. Voici un exemple d'utilisation.
1 2 3 4 5 6 |
>>> d1 = {"a": 1, "b": 2} >>> d2 = {"c": 3, "d": 4, "b": 22} >>> full = {**d1, **d2} >>> full {'a': 1, 'b': 22, 'c': 3, 'd': 4} >> |
update
, opérateurs |
ou **
),
et en cas de conflits sur les noms de clés, c'est la dernière valeur considérée qui écrase les précédentes (b
vaut 22 au final).
Nous avons vu, dans les chapitres précédents, qu'il était possible de spécifier le type de vos variables lors de leurs déclarations.
Il en va de même pour vos dictionnaires et vous pouvez même indiquer le type des clés et des valeurs qu'un dictionnaire doit contenir.
Voici un exemple de code indiquant que la variable months
sera typée en tant que dictionnaire de valeurs flottantes (set[float]
).
1 2 3 |
# Attention : Python 3.9 ou supérieur requis !!! months: dict[str, int] = {"janvier": 31, "février": 28, "mars": 31, "avril": 30} print(months) |
from typing import Dict
. Il faudra alors utiliser le type Dict[str, int]
. Voici un exemple d'utilisation.
1 2 3 4 5 |
from typing import Dict # Syntaxe recommandée pour des versions antérieures à Python 3.9 months: Dict[str, int] = {"janvier": 31, "février": 28, "mars": 31, "avril": 30} print(months) |
N'oubliez pas que certains IDEs peuvent vérifier les informations de typage : c'est le cas de PyCharm. Si vous tentez d'insérer autre chose qu'une paire de type « str / int », l'IDE pourra signaler cette incohérence. Voici une capture d'écran de PyCharm montrant cette capacité.
Vous pouvez aussi utiliser l'outil « mypy » pour vérifier la cohérence des types de votre programme. Voici un exemple de vérification.
[$> mypy test_typing.py test_typing.py:4: error: Invalid index type "int" for "Dict[str, int]"; expected type "str" test_typing.py:4: error: Incompatible types in assignment (expression has type "str", target has type "int") Found 2 errors in 1 file (checked 1 source file) $>
Exercice 1 : écrire un programme qui permet de saisir (dans une boucle) des noms de mois en anglais. A chaque saisie, il vous est demandé
de retrouver dans un dictionnaire le nombre de jours associé au mois et de l'afficher (pour le mois de février, on reverra 28). Si l'utilisateur
saisi exit
, le programme doit s'arrêter.
Exercice 2 : reprendre le programme précédent et permettre aussi la saisir des noms de mois en français. Pour ce faire, vous devrez utiliser un second dictionnaire pour gérer la traduction des mois en français vers les mois en anglais.
Exercice 3 : commencez par demander à un utilisateur de saisir une chaîne de caractères au clavier.
Ensuite, via une boucle for
appliquée sur la chaîne saisie, construire un dictionnaire dont les clés sont les différentes lettres
constituant la chaîne et les valeurs correspondent au nombre d'occurrences de chaque lettre. Terminer l'exercice en demandant à l'utilisateur de choisir
(autant de fois que nécessaire) une lettre et vous lui retournerez le nombre d'occurrences de cette lettre.
Voici une exemple d'exécution du programme demandé.
Veuillez saisir une chaîne de caractères : Hello World Veuillez saisir une lettre : d La lettre d apparaît 1 fois dans Hello World Veuillez saisir une lettre : l La lettre l apparaît 3 fois dans Hello World Veuillez saisir une lettre : q La lettre q n'est pas présente dans Hello World Veuillez saisir une lettre : exit Bye bye
Comme toujours, essayez de faire ces exercices sans regarder directement la correction ci-dessous. ;-)
Exercice 1 : voici ma proposition de correction.
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 |
# Un dictionnaire d'association "nom de mois / nb jours" months = { "january": 31, "february": 28, "march": 31, "april": 30, "may": 31, "june": 30, "july": 31, "august": 31, "september": 30, "october": 31, "november": 30, "december": 31 } print("Month requester - V1.0 :-)") is_running = True while is_running: month_name = input("Please enter a month name: ").lower() if month_name == "exit": is_running = False if month_name in months: print(f"Month {month_name} contains {months[month_name]} days") else: print("Unknown month", month_name) print("Bye bye") |
Et voici le résultat produit par cet exemple.
Month requester - V1.0 :-) Please enter a month name: january Month january contains 31 days Please enter a month name: february Month february contains 28 days Please enter a month name: trucary Unknown month trucary Please enter a month name: exit Bye bye
Exercice 2 : voici ma proposition de correction.
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 47 48 |
# Un dictionnaire d'association "nom de mois / nb jours" months = { "january": 31, "february": 28, "march": 31, "april": 30, "may": 31, "june": 30, "july": 31, "august": 31, "september": 30, "october": 31, "november": 30, "december": 31 } # Un second dictionnaire d'association des noms de mois français / anglais frTranslator = { "janvier": "january", "février": "february", "mars": "march", "avril": "april", "mai": "may", "juin": "june", "juillet": "july", "août": "august", "septembre": "september", "octobre": "october", "novembre": "november", "décembre": "december" } print("Month requester - V1.0 :-)") is_running = True while is_running: month_name = input("Please enter a month name: ").lower() if month_name == "exit": is_running = False elif month_name in months: print(f"Month {month_name} contains {months[month_name]} days") elif month_name in frTranslator: month_name = frTranslator[month_name] print(f"Month {month_name} contains {months[month_name]} days") else: print("Unknown month", month_name) print("Bye bye") |
Et voici le résultat produit par cet exemple.
Month requester - V1.0 :-) Please enter a month name: january Month january contains 31 days Please enter a month name: janvier Month janvier contains 31 days Please enter a month name: february Month february contains 28 days Please enter a month name: trucary Unknown month trucary Please enter a month name: exit Bye bye
Exercice 3 : voici ma proposition de correction.
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 |
# On demande la saisie de la chaîne initiale. the_string = input("Veuillez saisir une chaîne de caractères : ") # On parcours la chaîne pour calculer le nombre d'occurrences de chaque lettres. letters = {} # L'appel à lower permet de ne pas être embêté par la casse. for letter in the_string.lower(): if letter in letters: letters[letter] += 1 else: letters[letter] = 1 # On demande maintenant à l'utilisateur de vérifier la présence de quelques lettres. is_running = True while is_running: # L'appel à lower permet de ne pas être embêté par la casse. letter = input("Veuillez saisir une lettre : ").lower() if letter == "exit": is_running = False elif letter in letters: count = letters[letter] print("La lettre", letter, "apparaît", count, "fois dans", the_string) else: print("La lettre", letter, "n'est pas présente dans", the_string) print("Bye bye") |
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :