dict
A l’instar des list
, les dict
(pour dictionnaire) sont des conteneurs dynamiques.
Mais, alors que l’accès aux éléments d’une liste se fait grâce à un indice positionnel, les dictionnaires stockent en fait des associations entre objets python.
L’objet équivalent à l’indice est appelée la clef, et l’objet associé est appelée la valeur.
Avant d’expliciter la syntaxe donnons un exemple d’utilisation.
>>> mon_dico = dict()
>>> mon_dico
{}
>>> mon_dico["premiere_clef"] = "premiere_valeur"
>>> mon_dico
{'premiere_clef': 'premiere_valeur'}
>>> mon_dico[1] = [1, 2, 3]
>>> mon_dico[(1, 2)] = "alpha"
>>> mon_dico
{'premiere_clef': 'premiere_valeur', 1: [1, 2, 3], (1, 2): 'alpha'}
>>> mon_dico[1]
[1, 2, 3]
>>> mon_dico[(1, 2)]
'alpha'
On voit que l’on a utilisé comme clefs des objets de type str
, int
et tuple
. On indiquera à la fin de la leçon la règle pour qu’un objet puisse être utiliser comme clef.
On peut créer des dictionnaires de trois façons distinctes (c’était déjà le cas des listes).
Création littérale d’un dictionnaire via la syntaxe {clef1: valeur1, clef2: valeur2, ..., clef_n: valeur_n}
. Par exemple
>>> est_consonne = {"a": False, "b": True, "c": True, "d": True}
>>> est_consonne["a"]
False
>>> est_consonne["b"]
True
On voit ici une utilisation possible d’un dictionnaire comme alternative à une fonction. C’est utile lorsque les entrées possibles sont en nombre fini (et petit) et si la recette de l’association est compliquée à coder.
Par accumulation. On commence avec un dictionnaire vide et on le remplit clef après clef avec la syntaxe (déjà présentée ci-dessus) dico[clef] = valeur
. Donnons un exemple:
>>> code_to_car = dict()
>>> for code in range(50, 60):
... code_to_car[code] = chr(code)
...
>>> code_to_car
{50: '2', 51: '3', 52: '4', 53: '5', 54: '6', 55: '7', 56: '8', 57: '9', 58: ':', 59: ';'}
50 < 51 < ... < 59
donc on aurait pu techniquement utiliser une liste pour stocker le résultat.50
. Ainsi pour accéder au caractère pour l’unicode 55
l’indice serait 55 - 50
c’est à dire 5
.Finalement on peut faire des compréhensions de dictionnaires de la façon suivante:
>>> lettre_a_code = { lettre: ord(lettre) for lettre in "abcdefghijklmnopqrstuvwxyz"}
>>> lettre_a_code
{'a': 97, 'b': 98, 'c': 99, 'd': 100, 'e': 101, 'f': 102, 'g': 103, 'h': 104, 'i': 105, 'j': 106, 'k': 107, 'l': 108, 'm': 109, 'n': 110, 'o': 111, 'p': 112, 'q': 113, 'r': 114, 's': 115, 't': 116, 'u': 117, 'v': 118, 'w': 119, 'x': 120, 'y': 121, 'z': 122}
Note qu’en fait à la fois la clef et la valeur peuvent dépendre de la variable d’itération, et qu’on peut à la fois imbriquer les boucles et rajoute un filtre.
>>> table_multiplication = {(i,j): i * j for i in range(1, 11) for j in range(1, 11) if i <= j}
>>> table_multiplication
{(1, 1): 1, (1, 2): 2, (1, 3): 3, (1, 4): 4, (1, 5): 5, (1, 6): 6, (1, 7): 7, (1, 8): 8, (1, 9): 9, (1, 10): 10, (2, 2): 4, (2, 3): 6, (2, 4): 8, (2, 5): 10, (2, 6): 12, (2, 7): 14, (2, 8): 16, (2, 9): 18, (2, 10): 20, (3, 3): 9, (3, 4): 12, (3, 5): 15, (3, 6): 18, (3, 7): 21, (3, 8): 24, (3, 9): 27, (3, 10): 30, (4, 4): 16, (4, 5): 20, (4, 6): 24, (4, 7): 28, (4, 8): 32, (4, 9): 36, (4, 10): 40, (5, 5): 25, (5, 6): 30, (5, 7): 35, (5, 8): 40, (5, 9): 45, (5, 10): 50, (6, 6): 36, (6, 7): 42, (6, 8): 48, (6, 9): 54, (6, 10): 60, (7, 7): 49, (7, 8): 56, (7, 9): 63, (7, 10): 70, (8, 8): 64, (8, 9): 72, (8, 10): 80, (9, 9): 81, (9, 10): 90, (10, 10): 100}
REMARQUE en fait le constructeur dict
accepte aussi de faire certaines conversions.
>>> dict(a=1, b=2, c=3)
{'a': 1, 'b': 2, 'c': 3}
>>> dict([("a", 1), ("b", 2), ("c", 2)])
{'a': 1, 'b': 2, 'c': 2}
On a déjà vu qu’on peut manipuler individuellement les clefs via l’opérateur []
, et ce, à la fois pour la création et l’accès.
>>> mon_dico["clef"] = "valeur"
>>> mon_dico["clef"]
'valeur'
Mais dans certaines situations, on peut vouloir accéder à la valeur d’une clef qui pourrait ne pas encore avoir été crée or la version naïve fait planter python.
>>> mon_dico = dict()
>>> mon_dico["clef"]
KeyError:
clef
On a alors deux solutions pour résoudre le problème:
in
:>>> mon_dico = { "c": "v"}
>>> if "c" in mon_dico:
... print(f"clef: {'c'}, valeur: {mon_dico['c']}")
...
clef: c, valeur: v
>>> if "d" in mon_dico:
... print(f"clef: {'d'}, valeur: {mon_dico['d']}")
... else:
... print("La clef n'existe pas")
...
La clef n'existe pas
REMARQUE l’opérateur in
permet aussi de tester l’appartenance pour les list
et les tuples
.
On peut fournir une valeur par défaut à utiliser si jamais la clef n’existe pas via la méthode get
>>> mon_dico = {"c": "v"}
>>> print(mon_dico.get("c", "PAS DE TELLE CLEF"))
v
>>> print(mon_dico.get("d", "PAS DE TELLE CLEF"))
PAS DE TELLE CLEF
Si on veut la suite des clefs on peut utiliser une des deux syntaxes suivantes (pour être plus ou moins ostensible)
>>> lettre_to_code = { lettre: ord(lettre) for lettre in "abcdefghijkllmnopqrstuvwxyz" }
>>> for clef in lettre_to_code:
... print(clef, end=" | ")
...
a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z |
>>> for clef in lettre_to_code.keys():
... print(clef, end=" <> ")
...
a <> b <> c <> d <> e <> f <> g <> h <> i <> j <> k <> l <> m <> n <> o <> p <> q <> r <> s <> t <> u <> v <> w <> x <> y <> z <>
Si on veut au contraire itérer sur les valeurs:
>>> lettre_to_code = { lettre: ord(lettre) for lettre in "abcdefghijkllmnopqrstuvwxyz" }
>>> for valeur in lettre_to_code.values():
... print(valeur, end=" ")
...
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
Finalement si on veut itérer sur les couples (clef, valeur)
il faut faire
>>> lettre_to_code = { lettre: ord(lettre) for lettre in "abcdefghijkllmnopqrstuvwxyz" }
>>> for clef, valeur in lettre_to_code.items():
... print( f"{(clef, valeur)}", end=" | ")
...
('a', 97) | ('b', 98) | ('c', 99) | ('d', 100) | ('e', 101) | ('f', 102) | ('g', 103) | ('h', 104) | ('i', 105) | ('j', 106) | ('k', 107) | ('l', 108) | ('m', 109) | ('n', 110) | ('o', 111) | ('p', 112) | ('q', 113) | ('r', 114) | ('s', 115) | ('t', 116) | ('u', 117) | ('v', 118) | ('w', 119) | ('x', 120) | ('y', 121) | ('z', 122) |
ATTENTION il faut bien réaliser que l’ordre dans lequel on récupère les objets n’est garanti que les pour les versions récentes de python. Et il s’agit alors de l’ordre dans lequel les clef ont été rentrées.
En corollaire de cet “absence” d’ordre l’égalité entre deux dictionnaires ne tient pas compte de l’ordre.
>>> dico_1 = {"a": 1, "b": 2}
>>> dico_1
{'a': 1, 'b': 2}
>>> dico_2 = {"b": 2, "a":1}
>>> dico_2
{'b': 2, 'a': 1}
>>> dico_1 == dico_2
True
REMARQUE une syntaxe un peu barbare au premier abord mais très utile dans certaines situations permet de faire sauter les parenthèses d’un dictionnaire en précédant le nom du dictionnaire par **
. Pour les list
/tuples
on n’utilise que *
.
.>>> def ma_fonction(arg1, arg2, arg3):
... print(f"arg1: {arg1}")
... print(f"arg2: {arg2}")
... print(f"arg3: {arg3}")
...
>>> liste = [1, 2, 3]
>>> ma_fonction(*liste)
arg1: 1
arg2: 2
arg3: 3
>>> dico = dict(arg2=2, arg3=3, arg1=1)
>>> dico
{'arg2': 2, 'arg3': 3, 'arg1': 1}
>>> ma_fonction(**dico)
arg1: 1
arg2: 2
arg3: 3
L’utilisation de list
/tuple
correspond à l’appel par argument ordonnés alors que l’utilisation de dict
correspond à l’appel par arguments nommés.
ATTENTION les dict
sont généralement appelées tables de hachages. Pour que des objets soit utilisables comme clefs il faut qu’elles soient hachables. Sans rentrer dans des détails techniques (consulter la fiche wikipédia en lien précédent) on partira du principe qu’en python cela sous entend que l’objet ne doit pas être mutable. Ainsi si on essaye d’utiliser une list
:
>>> dico = dict()
>>> dico[[1, 2]] = "test"
------------------------------------------------------------------------------------------
<stdin> 1 <module>
1
TypeError:
unhashable type: 'list'
calcule_frequence
prenant en entrée texte: str
et retournant le dictionaire contenant la fréquences des caractères dans le texte.affiche_notes
prenant en entrée classe: dict[str: list[int]]
et renvoyant en sortie une chaine résumant les notes de la classe suivant l’exemple suivant.>>> classe = {"Bob": [5, 10, 15], "Alice": [10, 15, 20]}
>>> print(affiche_notes(classe))
Alice : 15.0 de moyenne
Notes : 10, 15, 20
Bob : 10.0 de moyenne
Notes : 5, 10, 15
>>> affiche_notes(classe)
'\nAlice : 15.0 de moyenne\n Notes : 10, 15, 20\nBob : 10.0 de moyenne\n Notes : 5, 10, 15\n'
Pour voir l’ensemble des méthodes disponibles pour un dict
>>> dir(dict)
Puis si on veut par exemple voir la documentation sur la méthode copy
>>> help(dict.copy)
Pour l’appartenance
>>> help("in")
Voir le fichier joint.