Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente |
python:bases:dictionnaires [2021/05/25 16:39] – [Quiz] phil | python:bases:dictionnaires [2022/08/16 08:27] (Version actuelle) – [9.2 Un dictionnaire pour indexer les enregistrements] phil |
---|
| [[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 : <html><a href="https://docs.python.org/fr/3.6/reference/index.html" target="_blank">référence du langage</a>, <html><a href="https://docs.python.org/fr/3/tutorial/datastructures.html#dictionaries" target="_blank">dictionnaire</a></html>, <html><a href="https://docs.python.org/fr/3.5/library/functions.html" target="_blank">fonctions natives</a></html> (built-in) |
| |
| * **Lectures connexes** |
| * **Real Python** |
| * <html><a href="https://realpython.com/python-ordereddict/" target="_blank">OrderedDict vs dict in Python: The Right Tool for the Job</a></html> |
| * <html><a href="https://realpython.com/sort-python-dictionary/" target="_blank">Sorting a Python Dictionary: Values, Keys, and More</a></html> |
| |
| * ** Mots-clés** : dictionnaire, parcours de dictionnaires. |
| |
| <callout type="warning" icon="true">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.</callout> |
| |
| | 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 | |
| |
| |
| * <html><a href="https://docs.python.org/fr/3.5/library/functions.html" target="_blank">Fonctions natives</a></html>** (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. |
| |
| <callout type="primary" icon="true">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**.</callout> |
| |
| ==== 2. Création ==== |
| <callout type="primary" icon="true">On utilise l'expression suivante : //nom_dictionnaire// = **dict()** ou //nom_dictionnaire// = **{}** pour créer des dictionnaires vides.</callout> |
| |
| //Exemples// |
| |
| <code python *.py> |
| # 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'} |
| </code> |
| |
| <callout type="primary" icon="true">Les **accolades** délimitent les **dictionnaires**.</callout> |
| |
| ==== 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// |
| |
| <code python *.py> |
| # 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 |
| </code> |
| |
| ==== 4. Ajout ou modification d'un élément ==== |
| <callout type="primary" icon="true">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**.</callout> |
| |
| //Exemples// |
| |
| <code python *.py> |
| 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'} |
| </code> |
| |
| ==== 5. Suppression d'éléments ==== |
| <callout type="primary" icon="true">On utilise **del**(//nom_dictionnaire//**[****//clé//****]**) ou //nom_dictionnaire//.**pop**("**clé**"). pop renvoie la valeur.</callout> |
| |
| <code python *.py> |
| 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) |
| </code> |
| |
| ==== 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 === |
| <callout type="primary" icon="true">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.</callout> |
| |
| <code python *.py> |
| 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 |
| </code> |
| |
| On peut obtenir séparément la liste des clés et des valeurs. |
| |
| === 6.2 Parcours des clés === |
| <callout type="primary" icon="true">On utilise la méthode **keys**() de la classe **dict**.</callout> |
| |
| <code python *.py> |
| placard = {"chemise": 6, "pantalon": 4, "chaussette": 10, "pull": 4} |
| for cle in placard.keys(): |
| print(cle) |
| |
| # Résultat |
| chemise |
| pantalon |
| chaussette |
| pull |
| </code> |
| |
| <callout type="primary" icon="true">L'itérateur sur les dictionnaires itère directement sur les clés.</callout> |
| |
| //Exemple// |
| <code python *.py> |
| # 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 |
| </code> |
| |
| === 6.3 Parcours des valeurs === |
| <callout type="primary" icon="true">On utilise la méthode **values**() de la classe **dict**.</callout> |
| |
| <code python *.py> |
| placard = {"chemise": 6, "pantalon": 4, "chaussette": 10, "pull": 4} |
| for valeur in placard.values(): |
| print(valeur) |
| |
| # Résultat |
| 6 |
| 4 |
| 10 |
| 4 |
| </code> |
| |
| <callout type="tip" icon="true">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.</callout> |
| |
| // Exemple // |
| |
| <code python *.py> |
| # 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 |
| </code> |
| ==== 7. Formation d'un dictionnaire à partir de deux listes ==== |
| <callout type="primary" icon="true">On utilise l'expression suivante : //nom_dictionnaire// = **dict**(**zip**(//listeClés//,//listeVal//))</callout> |
| |
| //Exemples// |
| |
| <code python *.py> |
| # 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} |
| </code> |
| |
| ==== 8. Transformation d'un dictionnaire en paramètres nommés d'une fonction ==== |
| |
| //Exemple// |
| |
| <code python *.py> |
| parametres = {"sep" : " >> ", "end" : " -\n"} |
| print("Voici", "un", "exemple", "d'appel", **parametres) |
| # Résultat : Voici >> un >> exemple >> d'appel - |
| </code> |
| |
| ==== 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// |
| |
| <code python *.py> |
| # 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 |
| </code> |
| |
| <callout type="warning" icon="true">Problème : l'accès à un enregistrement suppose ici que l'on connaisse sa position. |
| </callout> |
| |
| ===9.2 Un dictionnaire pour indexer les enregistrements === |
| <callout type="tip" icon="true">Pour modéliser ces informations, il est plus adapté d'utiliser, non pas une liste, mais un **dictionnaire de dictionnaires**.</callout> |
| |
| //Exemple// |
| <code python *.py> |
| 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é |
| </code> |
| ==== 9. Les méthodes de la classe dict ==== |
| * **Source** <html><a href="https://www.w3schools.com/python/python_ref_dictionary.asp" target="_blank">w3schools.com</a></html> |
| |
| ^ 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 ==== |
| * <html><a href="https://realpython.com/quizzes/python-dicts/" target="_blank">Python Dictionaries Quiz</a></html> |
| * <html><a href="https://realpython.com/quizzes/python-dictionary-iteration/" target="_blank">Python Dictionary Iteration Quiz</a></html> |