[[python:bases:ensembles|{{ :suivant.png?nolink&30|Ensembles}}]] [[:python:bases:tuples|{{ :retour.png?nolink&30|Tuples}}]] [[:python:accueilpython|{{ :iconemaison.jpg?nolink&30|Sommaire Python et microPython}}]] ===== Python - Dictionnaires ===== [Mise à jour le : 16/8/2022] * **Sources** * **Documentation** sur Python.org : référence du langage, dictionnaire, fonctions natives (built-in) * **Lectures connexes** * **Real Python** * OrderedDict vs dict in Python: The Right Tool for the Job * Sorting a Python Dictionary: Values, Keys, and More * ** Mots-clés** : dictionnaire, parcours de dictionnaires. Les mots ci-dessous sont dits "réservés". Ils ne peuvent pas être utilisés comme nom de variable. Les mots __soulignés__ sont une nouveauté de Python 3. Les mots en **gras** sont utilisés dans cette page. | and | continue | finally | **is** | raise | | as | def | **for** | lambda | return | | assert | **del** | from | __None__ | __True__ | | __async__ | elif | global | __nonlocal__ | try | | __await__ | else | if | not | **while** | | break | except | import | or | with | | class | __False__ | **in** | pass | yield | * Fonctions natives** (built-in)**((Fonctions toujours disponibles.)) utilisées dans les exemples : **dict**()((**Constructeur** : un constructeur est, en programmation orientée objet, une fonction particulière appelée lors de l'instanciation. Elle permet d'allouer la mémoire nécessaire à l'objet et d'initialiser ses attributs.)), **del**(), **print**(), **range**(), **zip**(). ---- ==== 1. Introduction ==== Le dictionnaire est une implémentation de table de hash. Il permet l'accès, l'insertion et le test d'appartenance indépendamment du nombre d'éléments. Le dictionnaire est un objet conteneur. À la différence des séquences, qui sont indexées par des nombres, les dictionnaires sont indexés par des **clés**, qui peuvent être de n'importe quel type immuable ; les chaînes de caractères et les nombres peuvent toujours être des clés. Les **dictionnaires** sont des objets **mutables**. Leur structure n'est pas ordonnée (ceci est dû à l'action de la fonction de hachage).Les **clés** doivent avoir un **type immuable**. ==== 2. Création ==== On utilise l'expression suivante : //nom_dictionnaire// = **dict()** ou //nom_dictionnaire// = **{}** pour créer des dictionnaires vides. //Exemples// # Première méthode dico = {} # dictionnaire vide dico = {'nom':'Martin','prenom':'Pierre-Emile'} # création en extension print(dico) # Résultat : {'nom': 'Martin', 'prenom': 'Pierre-Emile'} # Deuxième méthode dico = dict() # dictionnaire vide # La fonction native dict() construit un dictionnaire directement à partir d'une liste # de paires clé-valeur stockées sous la forme de tuples. dico = dict([('nom','Martin'),('prenom','Pierre-Emile')]) print(dico) # Résultat : {'nom': 'Martin', 'prenom': 'Pierre-Emile'} # ou # Construction à partir d'une liste de tuples et de la fonction native dict() l = [('nom','Martin'),('prenom','Pierre-Emile')] dico = dict(l) print(dico) # Résultat : {'nom': 'Martin', 'prenom': 'Pierre-Emile'} # Troisième méthode dico = dict(nom='Martin',prenom='Pierre-Emile') print(dico) # Résultat : {'nom': 'Martin', 'prenom': 'Pierre-Emile'} Les **accolades** délimitent les **dictionnaires**. ==== 3. Lecture de la valeur d'un élément ==== On accède à une valeur à partir de sa **clé** par //nom_dictionnaire//**[****//clé//****]**. Si la clé n'existe pas, une exception de type **KeyError** sera levée. //Exemple// # En faisant un test d'appartenance on évite la génération d'une erreur KeyError si la clé est absente if 'nom' in dico: print(dico["nom"]) # résultat : Martin ==== 4. Ajout ou modification d'un élément ==== Le dictionnaire est un type **mutable**, et donc on peut **modifier la valeur** associée à une clé. On utilise l'expression suivante : //nom_dictionnaire//**[****//clé//****]** = //**valeur**//. Et de la même jaçon, **ajouter une entrée**. //Exemples// dico = {} # La clé peut être une chaîne de caractères dico['nom']='Martin' dico['prenom']='Pierre-Emile' print(dico) #résultat : {'nom': 'Martin', 'prenom': 'Pierre-Emile'} # La clé peut être un tuple echiquier = {} echiquier[('a',1)] = 'tour blanche' print(echiquier) # résultat : {('a', 1): 'tour blanche'} ==== 5. Suppression d'éléments ==== On utilise **del**(//nom_dictionnaire//**[****//clé//****]**) ou //nom_dictionnaire//.**pop**("**clé**"). pop renvoie la valeur. placard = {"chemise":6,"pantalon":4} del(placard["chemise"]) print(placard) # Résultat : {'pantalon': 4} n = placard.pop("pantalon") print(placard) # Résultat : {} print(n,"pantalon(s) donné(s)") # Résultat : 4 pantalon(s) donné(s) ==== 6. Le parcours de dictionnaires ==== La méthode la plus fréquente pour parcourir tout un dictionnaire est à base de la méthode items. === 6.1 Parcours des clés et valeurs simultanément === On utilise la méthode **items** de la classe **dict**. Elle renvoie une **liste**, contenant les couples **clé : valeur**, sous la forme d'un tuple. placard = {"chemise": 6, "pantalon": 4, "chaussette": 10, "pull": 4} # A chaque tour de boucle, items renvoie un tuple constitué de la clé et de la valeur for cle, valeur in placard.items(): # notation de tuple unpacking print(cle, valeur) # Résultat chemise 6 pantalon 4 chaussette 10 pull 4 On peut obtenir séparément la liste des clés et des valeurs. === 6.2 Parcours des clés === On utilise la méthode **keys**() de la classe **dict**. placard = {"chemise": 6, "pantalon": 4, "chaussette": 10, "pull": 4} for cle in placard.keys(): print(cle) # Résultat chemise pantalon chaussette pull L'itérateur sur les dictionnaires itère directement sur les clés. //Exemple// # Dans l'exemple précédent, on obtient le même résultat san préciser la méthode keys() placard = {"chemise": 6, "pantalon": 4, "chaussette": 10, "pull": 4} for cle in placard: print(cle) # Résultat chemise pantalon chaussette pull === 6.3 Parcours des valeurs === On utilise la méthode **values**() de la classe **dict**. placard = {"chemise": 6, "pantalon": 4, "chaussette": 10, "pull": 4} for valeur in placard.values(): print(valeur) # Résultat 6 4 10 4 Les méthodes **keys**(), **values**() et **items**() retournent un objet particulier appelé : **une vue** (itérable et possédant le test d'appartenance). La caractéristique principale d'une vue est qu'elle est **mise à jour** en même temps que le dictionnaire. // Exemple // # Création du dictionnaire en extension placard = {"chemise": 6, "pantalon": 4, "chaussette": 10, "pull": 4} k = placard.keys() # Création d'une "vue" sur le dictionnaire placard print(k) # Résultat : dict_keys(['chemise', 'pantalon', 'chaussette', 'pull']) placard['short'] = 3 # Ajout d'un couple dans le dictionnaire placard print(placard) # Résultat : {'chemise': 6, 'pantalon': 4, 'chaussette': 10, 'pull': 4, 'short': 3} # La vue a été modifiée sans réaffectation print(k) # Résultat : dict_keys(['chemise', 'pantalon', 'chaussette', 'pull', 'short']) # Test d'appartenance sur une vue 'chemise' in k # Résultat : True 'ceinture in k # Résultat : False ==== 7. Formation d'un dictionnaire à partir de deux listes ==== On utilise l'expression suivante : //nom_dictionnaire// = **dict**(**zip**(//listeClés//,//listeVal//)) //Exemples// # Formation du dictionnaire dico à partir de deux listes cles=['a','b','c'] valeurs=[1,2,3] dico=dict(zip(cles,valeurs)) # Affichage print(dico) # résultat : {'a': 1, 'b': 2, 'c': 3} ==== 8. Transformation d'un dictionnaire en paramètres nommés d'une fonction ==== //Exemple// parametres = {"sep" : " >> ", "end" : " -\n"} print("Voici", "un", "exemple", "d'appel", **parametres) # Résultat : Voici >> un >> exemple >> d'appel - ==== 9. Gérer des enregistrements ==== Un enregistrement est une donnée composite qui contient plusieurs champs (struct ou un record dans d'autres langages). === 9.1 Implémenter un enregistrement comme un dictionnaire === //Exemple// # Enregistrement personnes = [ {'nom': 'Pierre', 'age': 25, 'email': 'pierre@example.com'}, {'nom': 'Paul', 'age': 18, 'email': 'paul@example.com'}, {'nom': 'Jacques', 'age': 52, 'email': 'jacques@example.com'}, ] # Pour l'anniversaire de Pierre on fera : personnes[0]['age'] += 1 # Affichage for personne in personnes: print(10*"=") for info, valeur in personne.items(): print(f"{info} -> {valeur}") # Résultat # ========== # nom -> Pierre # age -> 26 # email -> pierre@example.com # ========== # nom -> Paul # age -> 18 # email -> paul@example.com # ========== # nom -> Jacques # age -> 52 # email -> jacques@example.com Problème : l'accès à un enregistrement suppose ici que l'on connaisse sa position. ===9.2 Un dictionnaire pour indexer les enregistrements === Pour modéliser ces informations, il est plus adapté d'utiliser, non pas une liste, mais un **dictionnaire de dictionnaires**. //Exemple// personnes = [ {'nom': 'Pierre', 'age': 25, 'email': 'pierre@example.com'}, {'nom': 'Paul', 'age': 18, 'email': 'paul@example.com'}, {'nom': 'Jacques', 'age': 52, 'email': 'jacques@example.com'}, ] # on crée un index permettant de retrouver rapidement une personne dans la liste index_par_nom = {personne['nom']: personne for personne in personnes} index_par_nom # Résultat : {'Pierre': {'nom': 'Pierre', 'age': 26, 'email': 'pierre@example.com'}, # 'Paul': {'nom': 'Paul', 'age': 18, 'email': 'paul@example.com'}, # 'Jacques': {'nom': 'Jacques', 'age': 52, 'email': 'jacques@example.com'}} # On accède à l'age de Pierre par index_par_nom['Pierre']['age'] # Résultat : 26 # au lieu de personnes[0]['age'], ce qui est plus pertinent car un dictionnaire n'est pas ordonné ==== 9. Les méthodes de la classe dict ==== * **Source** w3schools.com ^ Fonction ^ Paramètres ^ Effet ^ Structure ^ |**clear**() | |Supprime tous les éléments du dictionnaire. | //d//.**clear**() | |**copy**() | |Renvoie une copie du dictionnaire. | //d//.**copy**() | |**fromkeys**() | clés,valeur |Crée un dictionnaire à partir d'une liste de clés prenant la **même valeur** ou **None**. | //d//.**fromkeys**(//keys//,//value//)| |**get**() | clé,defaut |Renvoie la valeur de l'élément avec la clé spécifiée ou la valeur par défaut si celle-ci est absente. | //d//.**get**(//clé//, //defaut//) | |**items**() | |Renvoie les paires clé-valeur du dictionnaire. | //d//.**items**() | |**keys**() | |Renvoie la liste des clés du dictionnaire. | //d//.**keys**() | |**popitem**() | |Renvoie et supprime le dernier élément du dictionnaire. | //d//.**popitem**() | |**pop**() | clé |Renvoie et supprime l'élément correspondant à la clé. | //d//.**pop**(//clé//) | |**setdefault**()| clé,valeur |Renvoie l'élément correspondant à la clé. S'il n'est pas présent, insère la clé avec la valeur dans le dictionnaire. |//d//.**setdefault**(//clé//,//valeur//) | |**update**() | iterable |Met à jour le dictionnaire. | //d//.**update**(iterable)| |**values**() | |Renvoie les valeurs du dictionnaire . | //d//.**values**() | ---- ==== Résumé ==== * Un dictionnaire est un objet conteneur associant des clés à des valeurs. * Pour créer un dictionnaire en extension, on utilise la syntaxe **dictionnaire = {clé1:valeur1,clé2:valeur2,clén:valeurn}**. * On ajoute ou on remplace un élément dans un dictionnaire par **dictionnaire[clé] = valeur**. * On supprime une clé et sa valeur avec le mot-clé **del** ou la méthode **pop**. * On parcourt un dictionnaire avec les méthodes **keys**(), **values**() et **items**(). * On capture les paramètres nommés passés à une fonction avec la syntaxe **def** //nom_fonction//(**//parametres_nommes// : (les paramètres nommés se trouvent dans le dictionnaire //parametres_nommes//). {{ :python:bases:realpython.png?nolink|}} ==== Quiz ==== * Python Dictionaries Quiz * Python Dictionary Iteration Quiz