Les dictionnaires

Les séquences trop contraignantes ?

Voyons cela sur un exemple: les pokémons ! Pour être exact, le jeu reposant sur les pokémons !

Prenons en un ! Au hasard, Magikarp !

Vous ne le savez peut être pas, mais celui-ci est un objet ou enregistrement dans une collection en contenant plusieurs centaines. Chaque pokémon a des caractéristiques bien définies dans le jeu que l’on appelle des descripteurs ou attributs ou encore keys. Voyez plutôt !

Quelques pokémons

Chacun d’entre eux porte un nom, un numéro d’identifiant (129 pour Magikarp), un nombre de points de vie (20HP -Health Points- pour Magikarp), …

Comment les représenter informatiquement ?

Immédiatement, l’emploi des séquences devient incontournable. Prenons les listes et gardons pour alléger le numéro d’identifiant (Id), le nom (Name), les points de vie (HP), son nombre de points de défense (DEF), son nombre de points de défense spécial (SP.DEF) et son type (Normal, Water, …)

Ainsi, Magikarp serait

pokemon = [129, 'Magikarp', 20, 55, 20, 'Water']

Mais, apparaissent déjà plusieurs défauts:

  • les séquences nous contraignent à choisir un ordre dans lequel écrire les données;

  • le manque relatif de lisibilité: on perd ainsi de vue ce que représente chacune des données. Par exemple, 55 est pokemon[3], mais à quel descripteur cela correspond ?

  • enfin, certains pokémons sont de deux types. Doit-on rajouter un élément vide à la fin de la liste précédente ?

Peut-on poursuivre avec les listes malgré tout ? Oui ! Mais nous le ferons pas !

Les dictionnaires à notre secours !

C’est là qu’interviennent les dictionnaires !

Ainsi, voici comment va s’écrire le dictionnaire qui va décrire un Magikarp.

pokemon = {'Id': 129, 'Name': 'Magikarp', 'HP': 20, 'DEF': 55, 'SP.DEF': 20, 'Type': 'Water'}

Vous voulez accéder à son 'HP' ? Rien de plus simple:

>>> pokemon['HP']
20

C’est simple non ?! Cela règle déjà le problème de lisibilité, mais pas que !

Est il encore nécessaire de préciser l'Id avant le Name ? Non ! Ce qui fait la différence entre les séquences et les dictionnaires: pas d’ordre des élèments dans ce dernier. Autrement dit, dans un dictionnaire, il n’y a pas de premier élèment ou de second, …

On pouvait écrire ce qui suit à la place:

>>> pokemon_v2 = {'Name': 'Magikarp', 'Type': 'Water', 'Id': 129, 'HP': 20, 'DEF': 55, 'SP.DEF': 20}
>>> pokemon == pokemon_v2
True

Cela confirme qu’il n’y a pas à se soucier de l’ordre dans lequel on donne les données tant que l’on précise à quelle descripteur/key correspond chaque valeur/value.

Définir un dictionnaire

En Python, un dictionnaire en Python est défini avec des accolades { et }.
Les descripteurs (keys) d’un dictionnaire sont récurcivement non mutables. Autrement dit, les descripteurs ne font intervenir que des nombres ou des chaînes de caractères ou des tuples d’élèments non mutables (tuples de nombres, tuples de chaînes de caractères, tuples mélangeant nombres et chaînes de caractères, des tuples de tuples de nombres …).

Les listes ne peuvent pas servir de descripteurs dans un dictionnaire, mais de valeurs oui !

Pas de contraintes sur les valeurs prises par ces descripteurs !

En pratique:

Créer un dictionnaire

  • Méthode 1: on peut écrire simplement le contenu 'Id': 129, ... entre accolades.

  • Méthode 2 (bien pratique): on ajoute les descripteurs et les valeurs associées à la volée.

    >>> pokemon = {}  # on définit un dico vide
    >>> pokemon['Id'] = 129
    >>> pokemon['Name'] = 'Magikarp'
    ...
    
  • Méthode 3: usage de la fonction dict() qui, à partir d’une liste de couples, retourne le dictionnaire associé.

    >>> poke = [('Name', 'Magikarp'), ('Type', 'Water'), ('Id', 129), ('HP', 20), ('DEF', 55), ('SP.DEF', 20)]
    >>> pokemon = dict(poke)
    >>> pokemon
    {'Name': 'Magikarp', 'Type': 'Water', 'Id': 129, 'HP': 20, 'DEF': 55, 'SP.DEF': 20}
    
  • Méthode 4 (plus rare) en supprimant un ou des descripteurs (et donc les valeurs associées)

    On va utiliser des fonctions semblables à celles vues sur les séquences: del et pop(). Revenir sur l'aide mémoire déjà donné.

    Avec pokemon = {'Id': 129, 'Name': 'Magikarp', 'HP': 20, 'DEF': 55, 'SP.DEF': 20, 'Type': 'Water', 'Type2': '?'}, supprimons la clé 'Type2' !

    >>> del pokemon['Type2'] 
    >>> pokemon
    {'Id': 129, 'Name': 'Magikarp', 'HP': 20, 'DEF': 55, 'SP.DEF': 20, 'Type': 'Water'}
    

    Autre solution:

    >>> pokemon.pop('Type2')   # affiche la valeur associée à la clé 'Type2' et la retire
    '?'
    >>> pokemon
    {'Id': 129, 'Name': 'Magikarp', 'HP': 20, 'DEF': 55, 'SP.DEF': 20, 'Type': 'Water'}
    
À vous d’essayez !

Définir les autres pokemons présents sur l’image déjà donnée en haut de cette page. Pour les pokemons admettant un deuxième type, on ajoutera le descripteur Type2.

Réponses ?

Accéder à certains élèments spécifiques d’un dictionnaire

Sur l’exemple, pokemon = {'Id': 129, 'Name': 'Magikarp', 'HP': 20, 'DEF': 55, 'SP.DEF': 20, 'Type': 'Water'}

  • Accéder à la valeur associer à un descripteur (déjà fait précédemment):

    >>> pokemon['Type']
    'Water'
    
  • Accéder à l’ensemble de descripteurs/keys du dictionnaire: usage de la méthode keys()

    Par exemple, en créant la liste contenant tous les descripteurs d’un dictionnaire: nom_du_dico.keys().

    >>> pokemon.keys()
    dict_keys(['Id', 'Name', 'HP', 'DEF', 'SP.DEF', 'Type'])
    

    Attention: le résultat n’est pas une liste, mais on peut itérer dessus avec une boucle for.

    Si vous voulez en créer une liste:

    >>> cles = list(pokemon.keys())
    >>> cles
    ['Id', 'Name', 'HP', 'DEF', 'SP.DEF', 'Type']
    

    Remarque importante: il ne faudra pas vous soucier de l’ordre des élèments de cette liste, mais seulement de son contenu.

    Autre solution: directement list(pokemon). Il faut comprendre par là que, par défaut, parcourir un dictionnaire c’est parcourir ses clés !

  • Accéder à l’ensemble de données/values du dictionnaire: usage de la méthode values()

    Par exemple, en créant la liste contenant tous les descripteurs d’un dictionnaire: nom_du_dico.values().

    >>> pokemon.values()
    dict_values([129, 'Magikarp', 20, 55, 20, 'Water'])
    

    Attention: là aussi le résultat n’est pas une liste !

    Si vous voulez en créer une liste:

    >>> valeurs = list(pokemon.values())
    >>> valeurs
    [129, 'Magikarp', 20, 55, 20, 'Water']
    

    Remarque importante: ici aussi, il ne faudra pas vous soucier de l’ordre des élèments de cette liste, mais seulement de son contenu.

  • Accéder à l’ensemble des couples (descripteur, valeur) du dictionnaire: usage de la méthode items()

    Par exemple, en créant la liste contenant tous les couples de (descripteur, valeur) associé au dictionnaire: nom_du_dico.items().

    >>> pokemon.items()
    dict_items([('Id', 129), ('Name', 'Magikarp'), ('HP', 20), ('DEF', 55), ('SP.DEF', 20), ('Type', 'Water')])
    

    Attention: là aussi le résultat n’est pas une liste !

    Si vous voulez en créer une liste:

    >>> couples = list(pokemon.items())
    >>> couples
    [('Id', 129), ('Name', 'Magikarp'), ('HP', 20), ('DEF', 55), ('SP.DEF', 20), ('Type', 'Water')]
    

    Remarque importante: ici encore, il ne faudra pas vous soucier de l’ordre des élèments de cette liste, mais seulement de son contenu.

Aide-mémoire (déjà donné dans le cours sur les séquences 3.1)

Document rassemblant les principales fonctions et méthodes sur les séquences notamment1


Notes de bas de page:

  1. Source du document: le MOOC “Apprendre à coder avec Python” sur la plateforme FUN qui rouvre régulièrement et qui est accessible gratuitement. ↩︎