Les dictionnaires

    Publicités

Users Who Are Viewing This Thread (Total: 0, Members: 0, Guests: 0)

Superman

V
Ancien staff
Dec 2, 2009
2,489
0
596
Création et édition de dictionnaires

Un dictionnaire est un type de données extrêmement puissant et pratique. Il se rapproche des listes sur certains points, mais sur beaucoup il diffère totalement. Python utilise ce type pour représenter beaucoup de fonctionnalités : on peut par exemple retrouver les attributs d'un objet grâce à un dictionnaire particulier.

Mais n'anticipons pas. Dans les deux chapitres précédents, nous avons découvert les listes. Les objets de ce type sont des objets conteneurs, dans lesquels on trouve d'autres objets. Pour accéder à ces objets contenus, il faut connaître leur position dans la liste. Cette position se traduit par des entiers, des indices, compris entre 0 (inclus) et la taille de la liste (non incluse). Tout ça vous devez déjà le savoir
smile.png
.

Le dictionnaire est aussi un objet conteneur. Il n'a quant à lui aucune structure ordonnée, à la différence des listes. De plus, pour accéder aux objets contenus dans le dictionnaire, on n'utilise pas nécessairement des indices mais des clés qui peuvent être de bien des types distincts.

Créer un dictionnaire


Là encore, je vous donne le nom de la classe sur laquelle se construit un dictionnaire : dict. Vous devriez du même coup trouver la première méthode d'instanciation du dictionnaire :

Code : Python Console 1
2
3
4
5
6
7
8
9
10
>>> mon_dictionnaire = dict()
>>> type(mon_dictionnaire)
<class 'dict'>
>>> mon_dictionnaire
{}
>>> # du coup, vous devriez trouver la deuxième manière de créer un dictionnaire vide
... mon_dictionnaire = {}
>>> mon_dictionnaire
{}
>>>




Les parenthèses délimitent les tuples, les crochets délimitent les listes et les accolades {} délimitent les dictionnaires.

Voyons comment ajouter des clés et valeurs dans notre dictionnaire vide :

Code : Python Console1
2
3
4
5
6
>>> mon_dictionnaire = {}
>>> mon_dictionnaire["pseudo"] = "Prolixe"
>>> mon_dictionnaire["mot de passe"] = "*"
>>> mon_dictionnaire
{'mot de passe': '*', 'pseudo': 'Prolixe'}
>>>




Nous indiquons entre crochets la clé à laquelle nous souhaitons accéder. Si la clé n'existe pas, elle est ajoutée au dictionnaire avec la valeur spécifiée après le signe =. Sinon, l'ancienne valeur à l'emplacement indiqué est remplacée par la nouvelle :

Code : Python Console1
2
3
4
5
6
7
>>> mon_dictionnaire = {}
>>> mon_dictionnaire["pseudo"] = "Prolixe"
>>> mon_dictionnaire["mot de passe"] = "*"
>>> mon_dictionnaire["pseudo"] = "6pri1"
>>> mon_dictionnaire
{'mot de passe': '*', 'pseudo': '6pri1'}
>>>




La valeur 'Prolixe' pointée par la clé 'pseudo' a été remplacée, à la ligne 4, par la valeur '6pri1'. Cela devrait vous rappeler la création de variables : si la variable n'existe pas, elle est créée, sinon elle est remplacée par la nouvelle valeur.

Pour accéder à la valeur d'une clé précise, c'est très simple :

Code : Python Console1
2
3
>>> mon_dictionnaire["mot de passe"]
'*'
>>>




Si la clé n'existe pas dans le dictionnaire, une exception de type KeyError sera levée.

Généralisons un peu tout ça : nous avons des dictionnaires, qui peuvent contenir d'autres objets. On place et accède à ces objets grâce à des clés. Un dictionnaire ne peut naturellement pas contenir deux clés identiques (comme on l'a vu, la seconde valeur écrase la première). En revanche, rien n'empêche d'avoir deux valeurs identiques dans le dictionnaire.

Nous avons utilisé ici, pour nos clés et nos valeurs, des chaînes de caractères. Ce n'est absolument pas obligatoire. Vous pouvez utiliser, comme des listes, des entiers comme clé :

Code : Python Console 1
2
3
4
5
6
7
8
9
10
>>> mon_dictionnaire = {}
>>> mon_dictionnaire[0] = "a"
>>> mon_dictionnaire[1] = "e"
>>> mon_dictionnaire[2] = "i"
>>> mon_dictionnaire[3] = "o"
>>> mon_dictionnaire[4] = "u"
>>> mon_dictionnaire[5] = "y"
>>> mon_dictionnaire
{0: 'a', 1: 'e', 2: 'i', 3: 'o', 4: 'u', 5: 'y'}
>>>




On a l'impression de recréer le fonctionnement d'une liste, mais ce n'est pas le cas : rappelez-vous qu'un dictionnaire n'a pas de structure ordonnée. Si vous supprimez par exemple l'indice 2, le dictionnaire, contrairement aux listes, ne va pas décaler toutes les clés d'indice supérieur à l'indice supprimé, il n'a pas été fait pour.

On peut utiliser quasiment tous les types comme clé, et on peut utiliser absolument tous les types comme valeur.

Voici un exemple un peu plus atypique de clés : on souhaite représenter un plateau d'échecs. Traditionnellement, on représente une case de l'échiquier par une lettre (de A à H) suivie d'un chiffre (de 1 à 8). La lettre définit la colonne, le chiffre la ligne. Regardez Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris! si vous n'êtes pas sûr de comprendre.

Pourquoi ne pas faire un dictionnaire avec, en clé un tuple contenant la lettre et le chiffre identifiant la case, et en valeur le nom de la pièce ?

Code : Python1
2
3
4
5
6
7
8
9
echiquier = {}
echiquier['a', 1] = "tour blanche" # en bas à gauche de l'échiquier
echiquier['b', 1] = "cavalier blanc" # à droite de la tour
echiquier['c', 1] = "fou blanc" # à droite du cavalier
echiquier['d', 1] = "reine blanche" # à droite du fou
# ... première ligne des blancs
echiquier['a', 2] = "pion blanc" # devant la tour
echiquier['b', 2] = "pion blanc" # devant le cavalier, à droite du pion
# ... seconde ligne des blancs




Dans cet exemple, nos tuples sont sous-entendus. On ne les place pas entre parenthèses. Python comprend qu'on veut créer des tuples, ce qui est bien, mais l'important est que vous le compreniez bien aussi. Certains cours encouragent à toujours placer des parenthèses autour des tuples quand on les utilise. Pour ma part, je pense que si vous gardez à l'esprit qu'il s'agit de tuples, que vous n'avez aucune peine à l'identifier, ça suffit. Si vous faites la confusion, mettez des parenthèses autour des tuples en toute circonstance.

On peut aussi créer des dictionnaires déjà remplis :

Code : Python1
placard = {"chemise":3, "pantalon":6, "tee-shirt":7}




On précise entre accolades la clé, le signe deux points « : » et la valeur correspondante. On sépare les différents couples clé:valeur par une virgule. C'est d'ailleurs comme ça que Python vous affiche un dictionnaire quand vous lui demandez.

Certains ont peut-être essayé de créer des dictionnaires déjà remplis avant que je ne le montre. Une petite précision, si vous avez entré une instruction similaire :

Code : Python1
mon_dictionnaire = {'pseudo', 'mot de passe'}




Dans cette occasion, ce n'est pas un dictionnaire que vous créez, mais un set.

Un set est un objet conteneur, lui aussi, très semblable aux listes, sauf qu'il ne peut contenir deux objets identiques. Vous ne pouvez trouver dans un set deux fois l'entier 3 par exemple. Je vous laisse vous renseigner sur les sets si vous le désirez.

Supprimer des clés d'un dictionnaire


Comme pour les listes, vous avez deux possibilités, mais elles reviennent sensiblement au même :


  • le mot-clé del ;
  • la méthode de dictionnaire pop.


Je ne vais pas m'attarder sur le mot-clé del, il fonctionne de la même façon que pour les listes :

Code : Python1
2
placard = {"chemise":3, "pantalon":6, "tee shirt":7}
del placard["chemise"]




La méthode pop supprime également la clé précisée, mais elle retourne la valeur supprimée.

Code : Python Console1
2
3
4
>>> placard = {"chemise":3, "pantalon":6, "tee shirt":7}
>>> placard.pop("chemise")
3
>>>




La méthode pop retourne la valeur qui a été supprimée en même temps que la clé. Ce peut être parfois utile.

Voilà pour le tour d'horizon. Ce fut bref et vous n'avez pas vu toutes les méthodes, bien entendu. Je vous laisse consulter l'aide pour une liste détaillée.

Un peu plus loin


On se sert parfois des dictionnaires pour stocker des fonctions.

Je vais juste vous montrer rapidement le mécanisme sans trop m'y attarder. Là, je compte sur vous pour faire des tests si vous êtes intéressé. C'est encore un petit quelque chose que vous n'utiliserez peut-être pas tous les jours mais qui peut être utile à connaître.

Les fonctions sont manipulables comme des variables. Ce sont des objets, un peu particuliers mais des objets tout de même. Donc on peut les prendre pour valeur d'affectation ou les ranger dans des listes ou dictionnaires. C'est pourquoi je présente cette fonctionnalité à présent, auparavant j'aurais manqué d'exemples pratiques.

Code : Python Console1
2
3
4
>>> print_2 = print # l'objet print_2 pointera sur la fonction print
>>> print_2("Affichons un message")
Affichons un message
>>>




On copie la fonction print dans une autre variable print_2. On peut ensuite appeler print_2 et la fonction va afficher le texte entré, tout comme print l'aurait fait.

En pratique, on affecte rarement des fonctions comme cela. C'est peu utile. Par contre, on met parfois des fonctions dans des dictionnaires :

Code : Python Console 1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> def fete():
... print("C'est la fête.")
...
>>> def oiseau():
... print("Fais comme l'oiseau...")
...
>>> fonctions = {}
>>> fonctions["fete"] = fete # on ne met pas les parenthèses
>>> fonctions["oiseau"] = oiseau
>>> fonctions["oiseau"]
<function oiseau at 0x00BA5198>
>>> fonctions["oiseau"]() # on essaye de l'appeler
Fais comme l'oiseau...
>>>




Prenons dans l'ordre si vous le voulez bien :


  • On commence par définir deux fonctions, fete et oiseau (pardonnez l'exemple
    langue.png
    )
  • On créée un dictionnaire nommé fonctions
  • On met dans notre dictionnaire nos fonctions fete et oiseau. La clé pointant vers la fonction est le nom de la fonction, tout bêtement, mais on aurait pu lui donner un nom plus original
    smile.png
  • On essaye d'accéder à notre fonction oiseau en entrant fonctions["oiseau"]. Python nous retourne un truc assez moche, <function oiseau at 0x00BA5198>, mais vous comprenez l'idée : c'est bel et bien notre fonction oiseau. Mais pour l'appeler, il faut des parenthèses, comme toute fonction qui se respecte
  • En entrant fonctions["oiseau"]() , on accède à la fonction oiseau et on l'appelle dans la foulée.


On peut stocker les références des fonctions dans n'importe quel objet conteneur, des listes, des dictionnaires... et d'autres classes, quand nous apprendrons à en faire. Je ne vous demande pas de comprendre absolument la manipulation des références des fonctions, essayez de retenir cet exemple. Dans tous les cas, nous aurons l'occasion d'y revenir
smile.png
.
Les méthodes de parcours

Comme vous pouvez le penser, on ne parcourt pas tout à fait un dictionnaire comme une liste. La différence n'est pas si énorme que ça, mais la plupart du temps, on passe par des méthodes de dictionnaire.

Parcours des clés


Peut-être avez-vous déjà essayé par vous-même de parcourir un dictionnaire comme on l'a fait pour les listes :

Code : Python Console1
2
3
4
5
6
7
8
>>> fruits = {"pomme":21, "melon":3, "poire":31}
>>> for cle in fruits:
... print(cle)
...
melon
poire
pomme
>>>




Comme vous le voyez, si on essaye de parcourir un dictionnaire « simplement », on parcourt en réalité la liste des clés contenues dans le dictionnaire.

Mais... les clés ne s'affichent pas dans l'ordre dans lesquelles on les a entrées... c'est normal ?


Les dictionnaires n'ont pas de structure ordonnée, gardez-le à l'esprit. Donc en ce sens oui, c'est tout à fait normal.

Une méthode de la classe dict permet d'obtenir ce même résultat. Personnellement, je l'utilise plus fréquemment car on est sûr, en lisant l'instruction, que c'est la liste des clés que l'on parcourt :

Code : Python Console1
2
3
4
5
6
7
8
>>> fruits = {"pomme":21, "melon":3, "poire":31}
>>> for cle in fruits.keys():
... print(cle)
...
melon
poire
pomme
>>>




La méthode keys (« clés » en anglais) retourne la liste des clés contenues dans le dictionnaire. En vérité, ce n'est pas tout à fait une liste (essayez d'entrer dans votre interpréteur fruits.keys() ), mais c'est un ensemble qui se parcourt tout à fait comme une liste.

Parcours des valeurs


On peut aussi parcourir les valeurs contenues dans un dictionnaire. Pour ce faire, on utilise la méthode values (« valeurs » en anglais).

Code : Python Console1
2
3
4
5
6
7
8
>>> fruits = {"pomme":21, "melon":3, "poire":31}
>>> for valeur in fruits.values():
... print(valeur)
...
3
31
21
>>>




Cette méthode est peu utilisée pour un parcours, car il est plus pratique de parcourir la liste des clés, cela suffit pour avoir les valeurs correspondantes. Mais on peut aussi, bien entendu, l'utiliser dans une condition :

Code : Python Console1
2
3
4
5
>>> if 21 in fruits.values():
... print("Un des fruits se trouve dans la quantité 21.")
...
Un des fruits se trouve dans la quantité 21.
>>>




Parcours des clés et valeurs simultanément


Pour avoir en même temps les indices et les objets d'une liste, on utilise la fonction enumerate, j'espère que vous vous en souvenez
smile.png
. Pour faire la même chose avec les dictionnaires, on utilise la méthode items. Elle retourne une liste, contenant les couples clé:valeur, sous la forme d'un tuple. Voyons comment l'utiliser :

Code : Python Console1
2
3
4
5
6
7
8
>>> fruits = {"pomme":21, "melon":3, "poire":31}
>>> for cle,valeur in fruits.items():
... print("La clé {0} contient la valeur {1}.".format(cle, valeur))
...
La clé melon contient la valeur 3.
La clé poire contient la valeur 31.
La clé pomme contient la valeur 21.
>>>




Il est parfois très pratique de parcourir un dictionnaire avec ses clés et les valeurs associées.

Entraînez-vous, il n'y a que cela de vrai. Pourquoi pas reprendre l'exercice du chapitre précédent, avec notre inventaire de fruits ? Sauf que le type de l'inventaire ne serait pas une liste mais un dictionnaire associant les noms des fruits aux quantités ?

Il nous reste une petite fonctionnalité supplémentaire à voir, et on en aura fini avec les dictionnaires.
Les dictionnaires et paramètres de fonction

Ça ne vous rappelle pas quelque chose ? J'espère bien que si, on a vu quelque chose similaire dans le chapitre précédent
clin.png
.

Si vous vous souvenez, on avait réussi à intercepter tous les paramètres de notre fonction... sauf les paramètres nommés.

Récupérer les paramètres nommés dans un dictionnaire


Il existe aussi une façon de capturer les paramètres nommés d'une fonction. Dans ce cas toutefois, ils sont placés dans un dictionnaire. Si par exemple vous appelez la fonction ainsi : fonction(parametre='a') , vous aurez, dans le dictionnaire capturant les paramètres nommés, une clé 'parametre' liée à la valeur 'a'. Voyez plutôt :

Code : Python Console 1
2
3
4
5
6
7
8
9
10
11
>>> def fonction_inconnue(**parametres_nommes):
... """Fonction permettant de voir comment récupérer les paramètres nommés
... dans un dictionnaire.
... """
... print("J'ai reçu en paramètres nommés : {0}.".format(parametres_nommes))
...
>>> fonction_inconnue() # aucun paramètre
J'ai reçu en paramètres nommés : {}
>>> fonction_inconnue(p=4, j=8)
J'ai reçu en paramètres nommés : {'p': 4, 'j': 8}
>>>




Pour capturer tous les paramètres nommés non précisés dans un dictionnaire, il faut mettre deux étoiles ** avant le nom du paramètre.

Si vous passez des paramètres non nommés à cette fonction, Python lèvera une exception.

Si bien que pour avoir une fonction qui accepte n'importe quel type de paramètres, nommés ou non, dans n'importe quel ordre, dans n'importe quelle quantité, il faut la déclarer ainsi :

Code : Python1
def fonction_inconnue(*en_liste, **en_dictionnaire):




Tous les paramètres non nommés se retrouveront dans la variable en_liste et les paramètres nommés dans la variable en_dictionnaire.

Mais à quoi ça peut bien servir, d'avoir une fonction qui accepte n'importe quel paramètre ?


Pour l'instant à pas grand chose, mais ça viendra. Quand on abordera le chapitre sur les décorateurs, vous vous en souviendrez et vous pourrez vous féliciter de connaître cette fonctionnalité
clin.png
.

Transformer un dictionnaire en paramètres nommés d'une fonction


Là encore, on peut faire exactement l'inverse : transformer un dictionnaire en paramètres nommés d'une fonction. Voyons un exemple tout simple :

Code : Python Console1
2
3
4
>>> parametres = {"sep":" >> ", "end":" -\n"}
>>> print("Voici", "un", "exemple", "d'appel", **parametres)
Voici >> un >> exemple >> d'appel -
>>>




Les paramètres nommés sont transmis à la fonction par un dictionnaire. Pour indiquer à Python que le dictionnaire doit être transmis comme des paramètres nommés, on place deux étoiles avant son nom ** dans l'appel de la fonction.

Comme vous pouvez le voir, c'est comme si nous avions écrit :

Code : Python Console1
2
3
>>> print("Voici", "un", "exemple", "d'appel", sep=" >> ", end= -\n")
Voici >> un >> exemple >> d'appel -
>>>




Pour l'instant, vous devez trouver que c'est bien se compliquer la vie pour si peu. Nous verrons dans la suite de ce cours qu'il n'en est rien, en fait, même si nous n'utilisons pas cette fonctionnalité tous les jours
clin.png
.


Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!