MARTIN, Gilles
ZURMÜHLE, Martin
Herbert List
Programmation Python/Dictionnaires
Déclarations.
Le dictionnaire ou n'est pas une séquence mais un autre type composite. Ils ressemblent aux listes dans une certaine mesure (ils sont modifiables comme elles), mais les éléments que nous allons y enregistrer ne seront pas disposés dans un ordre immuable. En revanche, nous pourrons accéder à n'importe lequel d'entre eux à l'aide d'un index spécifique que l'on appellera une clé, laquelle pourra être alphabétique, numérique, ou même d'un type composite sous certaines conditions.
Création d'un dictionnaire.
À titre d'exemple, nous allons créer un dictionnaire de langue, pour la traduction de termes informatiques anglais en français. Dans ce dictionnaire, les index seront des chaînes de caractères.
Puisque le type dictionnaire est un type modifiable, nous pouvons commencer par créer un dictionnaire vide, puis le remplir petit à petit. Du point de vue syntaxique, on reconnaît une structure de données de type dictionnaire au fait que ses éléments sont enfermés dans "une paire d'accolades". Un dictionnaire vide sera donc noté codice_1 :
dico['computer'] = 'ordinateur'
dico['mouse'] ='souris'
dico['keyboard'] ='clavier'
print dico
Comme vous pouvez l'observer dans la ligne ci-dessus, un dictionnaire apparaît comme une série d'éléments séparés par des virgules (le tout étant enfermé entre deux accolades}. Chacun de ces éléments est constitué d'une paire d'objets : un index et une valeur, séparés par un double point.
Dans un dictionnaire, les index s'appellent des "clés", et les éléments peuvent donc s'appeler "des paires clé-valeur". Vous pouvez constater que l'ordre dans lequel les éléments apparaissent à la dernière ligne ne correspond pas à celui dans lequel nous les avons fournis. Cela n'a strictement aucune importance : nous n'essaierons jamais d'extraire une valeur d'un dictionnaire à l'aide d'un index numérique. Au lieu de cela, nous utiliserons les clés :
Contrairement à ce qui se passe avec les listes, il n'est pas nécessaire de faire appel à une méthode particulière pour ajouter de nouveaux éléments à un dictionnaire : il suffit de créer une nouvelle paire clé-valeur.
Opérations sur les dictionnaires.
Pour en enlever, vous utiliserez l'instruction codice_2. Créons pour l'exemple un autre dictionnaire, destiné cette fois à contenir l'inventaire d'un stock de fruits. Les index (ou clés) seront les noms des fruits, et les valeurs seront les masses de ces fruits répertoriées dans le stock (il s'agit donc cette fois de valeurs de type numérique).
Si le patron décide de liquider toutes les pommes et de ne plus en vendre, nous pouvons enlever cette entrée dans le dictionnaire :
La fonction codice_3 est utilisable avec un dictionnaire : elle en renvoie le nombre d'éléments.
Les dictionnaires sont des objets.
On peut appliquer aux dictionnaires un certain nombre de "méthodes" spécifiques :
"keys" et "values".
La méthode codice_4 renvoie la liste des clés utilisées dans le dictionnaire :
La méthode codice_5 renvoie la liste des valeurs mémorisées dans le dictionnaire :
"has_key".
La méthode codice_6 permet de savoir si un dictionnaire comprend une clé déterminée. On fournit la clé en argument, et la méthode renvoie une valeur 'vraie' ou 'fausse' (en fait, 1 ou 0), suivant que la clé est présente ou pas :
"items".
La méthode codice_7 extrait du dictionnaire une liste équivalente de tuples :
Il est donc utilisé pour les "foreach" :
for key, value in invent.items():
 print "Clé : %s, valeur : %s." % (key, value)
"copy".
La méthode codice_8 permet d'effectuer une vraie copie d'un dictionnaire. Il faut savoir en effet que la simple affectation d'un dictionnaire existant à une nouvelle variable crée seulement une nouvelle référence vers le même objet, et non un nouvel objet ("aliasing"). Par exemple, l'instruction ci-dessous ne définit pas un nouveau dictionnaire (contrairement aux apparences) :
»> stock = invent
»> print stock
»> del invent['bananes']
»> print stock
Si nous modifions "invent", alors codice_9 aussi est modifié, et vice-versa (ces deux noms désignent en effet le même objet dictionnaire dans la mémoire de l'ordinateur).
Pour obtenir une vraie copie (indépendante) d'un dictionnaire préexistant, il faut employer la méthode codice_8 :
»> magasin = stock.copy()
»> magasin['prunes'] = 561
»> print magasin
»> print stock
»> print invent
"update".
Il est possible de concaténer deux dictionnaires avec cette méthode :
»> d.update(ud)
»> d
"sorted".
Pour trier un dictionnaire par clé :
d = sorted(d.items(), key=lambda x: x[0])
Pour trier par valeur :
d = sorted(d.items(), key=lambda x: x[1])
Pour l'inverse, ajouter : codice_11.
Parcours d'un dictionnaire.
Vous pouvez utiliser une boucle for pour traiter successivement tous les éléments contenus dans un dictionnaire, mais attention :
Exemple :
Si vous souhaitez effectuer un traitement sur les valeurs, il vous suffit alors de récupérer chacune d'elles à partir de la clé correspondante :
Cette manière de procéder n'est cependant pas idéale, ni en termes de performances ni même du point de vue de la lisibilité. Il est recommandé de plutôt faire appel à la méthode codice_7 décrite à la section précédente :
Les clés ne sont pas nécessairement des chaînes de caractères.
Jusqu'à présent nous avons décrit des dictionnaires dont les clés étaient à chaque fois des valeurs de type "string". En fait nous pouvons utiliser en guise de clés n'importe quel type de donnée non modifiable : des entiers, des réels, des chaînes de caractères, et même des tuples.
Considérons par exemple que nous voulions répertorier les arbres remarquables situés dans un grand terrain rectangulaire. Nous pouvons pour cela utiliser un dictionnaire, dont les clés seront des tuples indiquant les coordonnées x,y de chaque arbre : 
Vous pouvez remarquer que nous avons allégé l'écriture à partir de la troisième ligne, en profitant du fait que les parenthèses délimitant les tuples sont facultatives (à utiliser avec prudence !).
Dans ce genre de construction, il faut garder à l'esprit que le dictionnaire contient des éléments seulement pour certains couples de coordonnées. Ailleurs, il n'y a rien. Par conséquent, si nous voulons interroger le dictionnaire pour savoir ce qui se trouve là où il n'y a rien, comme par exemple aux coordonnées (2,1), nous allons provoquer une erreur : 
Pour résoudre ce petit problème, nous pouvons utiliser la méthode codice_13 :
Le premier argument transmis à cette méthode est la clé de recherche, le second argument est la valeur que nous voulons obtenir en retour si la clé n'existe pas dans le dictionnaire.
Les dictionnaires ne sont pas des séquences.
Comme vous l'avez vu plus haut, les éléments d'un dictionnaire ne sont pas disposés dans un ordre particulier. Des opérations comme la concaténation et l'extraction (d'un groupe d'éléments contigus) ne peuvent donc tout simplement pas s'appliquer ici. Si vous essayez tout de même, Python lèvera une erreur lors de l'exécution du code :
»> print arb[1:3]
 ***** Erreur : KeyError: slice(1, 3, None) *****
Vous avez vu également qu'il suffit d'affecter un nouvel indice (une nouvelle clé) pour ajouter une entrée au dictionnaire. Cela ne marcherait pas avec les listes :
»> invent['cerises'] = 987
»> print invent
»> liste =['jambon', 'salade', 'confiture', 'chocolat']
»> liste[4] ='salami'
 ***** IndexError: list assignment index out of range *****
Du fait qu'ils ne sont pas des séquences, les dictionnaires se révèlent donc particulièrement précieux pour gérer des ensembles de données où l'on est amené à effectuer fréquemment des ajouts ou des suppressions, dans n'importe quel ordre. Ils remplacent avantageusement les listes lorsqu'il s'agit de traiter des ensembles de données numérotées, dont les numéros ne se suivent pas.
Exemple :
etc. 
Construction d'un histogramme à l'aide d'un dictionnaire.
Les dictionnaires constituent un outil très élégant pour construire des histogrammes.
Supposons par exemple que nous voulions établir l'histogramme qui représente la fréquence d'utilisation de chacune des lettres de l'alphabet dans un texte donné. L'algorithme permettant de réaliser ce travail est extraordinairement simple si on le construit sur base d'un dictionnaire :
Nous commençons par créer un dictionnaire vide : codice_14. Ensuite, nous allons remplir ce dictionnaire en utilisant les caractères de l'alphabet en guise de clés. Les valeurs que nous mémoriserons pour chacune de ces clés seront les fréquences des caractères correspondants dans le texte. Afin de calculer celles-ci, nous effectuons un parcours de la chaîne de caractères texte. Pour chacun de ces caractères, nous interrogeons le dictionnaire à l'aide de la méthode codice_13, en utilisant le caractère en guise de clé, afin d'y lire la fréquence déjà mémorisée pour ce caractère. Si cette valeur n'existe pas encore, la méthode codice_13 doit renvoyer une valeur nulle. Dans tous les cas, nous incrémentons la valeur trouvée, et nous la mémorisons dans le dictionnaire à l'emplacement qui correspond à la clé (c'est-à-dire au caractère en cours de traitement).
Pour fignoler notre travail, nous pouvons encore souhaiter afficher l'histogramme dans l'ordre alphabétique. Pour ce faire, nous pensons immédiatement à la méthode codice_17, mais celle-ci ne peut s'appliquer qu'aux listes. Qu'à cela ne tienne ! Nous avons vu plus haut comment nous pouvions convertir un dictionnaire en une liste de tuples :
Contrôle du flux d'exécution à l'aide d'un dictionnaire.
Il arrive fréquemment que l'on ait à diriger l'exécution d'un programme dans différentes directions, en fonction de la valeur prise par une variable. Vous pouvez bien évidemment traiter ce problème à l'aide d'une série d'instructions codice_19 , mais cela peut devenir assez lourd et inélégant si vous avez affaire à un grand nombre de possibilités. Exemple :
materiau = raw_input("Choisissez le matériau : ")
if materiau == 'fer':
 fonctionA()
elif materiau == 'bois':
 fonctionC()
elif materiau == 'cuivre':
 fonctionB()
elif materiau == 'pierre':
 fonctionD()
elif ... etc ...
Les langages de programmation proposent souvent des instructions spécifiques pour traiter ce genre de problème, telles les instructions codice_20 ou codice_21 du C ou du Pascal. Python n'en propose aucune, mais vous pouvez vous tirer d'affaire dans bien des cas à l'aide d'une liste, ou mieux encore à l'aide d'un dictionnaire. Exemple :
materiau = raw_input("Choisissez le matériau : ")
dico = {'fer':fonctionA,
 'bois':fonctionC,
 'cuivre':fonctionB,
 'pierre':fonctionD,
dico[materiau]()
Les deux instructions ci-dessus pourraient être condensées en une seule, mais nous les laissons séparées pour bien détailler le mécanisme :
Vous pouvez encore améliorer la technique ci-dessus en remplaçant cette instruction par sa variante ci-dessous, qui fait appel à la méthode codice_13 afin de prévoir le cas où la clé demandée n'existerait pas dans le dictionnaire (vous obtenez de cette façon l'équivalent d'une instruction codice_25 terminant une longue série de codice_26) :
dico.get(materiau, fonctAutre)()
Lorsque la la valeur de la variable "materiau "ne correspond à aucune clé du dictionnaire, c'est la fonction codice_27 qui est invoquée.
Différences entre deux dictionnaires.
Par exemple pour savoir quels sont les éléments importés :
d1 = locals().copy()
import pywikibot
d2 = locals()
print(set(d2) - set(d1))