Skip to content

1 2 3 1 Fiche dictionnaires

Les dictionnaires

Introduction

Définition simple

Un dictionnaire est une collection de paires clé / valeur. L'objet Python est dict.

Exemples

Voici un exemple de dictionnaire :

{'nom':'von rossum', 'prenom':'guido', 'langage':'python'}

Les pairs clés / valeurs sont entourées par des accolades et séparées les unes des autres par des virgules. Un caractère deux-points (:) sépare la clé de sa valeur.

Dans cet exemple, les clés sont des str : 'nom', 'prenom' et 'langage' ; les valeurs associées sont, respectivement, 'von rossum', 'guido' et 'python'. Bien sûr on peut avoir d'autres types pour les clés et pour les valeurs :

{(0, 1):True, 'nb_points':3, (0, 0):False, (-1, 0):True}

Dans ce deuxième exemple, on a des clés de type tuple et str et des valeurs de type int et bool.

Le dictionnaire vide :

>>> dico_vide = {}
>>> autre_dico_vide = dict()

Définition plus complète

Voici la définition qu'on trouve dans la documentation officielle de Python:

Un autre type de donnée très utile, natif dans Python, est le dictionnaire (voir Les types de correspondances — dict). Ces dictionnaires sont parfois présents dans d'autres langages sous le nom de « mémoires associatives » ou de « tableaux associatifs ». À 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. Des n-uplets peuvent être utilisés comme clés s'ils ne contiennent que des chaînes, des nombres ou des n-uplets ; si un n-uplet contient un objet muable, de façon directe ou indirecte, il ne peut pas être utilisé comme une clé. Vous ne pouvez pas utiliser des listes comme clés, car les listes peuvent être modifiées en place en utilisant des affectations par position, par tranches ou via des méthodes comme append() ou extend().

Qu'il faut complèter par la définition d'un type de correspondance :

Un objet mapping fait correspondre des valeurs hashables à des objets arbitraires. Les mappings sont des objets muables. Il n'existe pour le moment qu'un type de mapping standard, le dictionary.

On a alors la contrainte forte sur les clés : une clé doit être un type hashable. C'est-à-dire que la valeur renvoyée par une fonction de hachage doit être constante, on parle d'empreinte. Concrètement pour nos dictionnaires, nous pouvons utiliser :

  • les types numériques
  • les str
  • les tuple qui ne contiennent que des types hashables directement ou indirectement.

Construction d'un dictionnaire

Rappelons qu'une clé doit être un objet hashable : pour simplifier disons non modifiable. Une TypeError est produite sinon :

>>> bad_dico = {[1]:'liste'}
TypeError                                 Traceback (most recent call last)
<ipython-input-1-33ed97c0d09f> in <module>
----> 1 bad_dico = {[1]:'liste'}

TypeError: unhashable type: 'list'

En extension

On l'a vu dans l'introduction, il suffit de lister les paires clé / valeur entre accolades :

ville = {'nom':'lyon', 'population':513275, 'annee':2015}

Par la fonction dict

Voici quelques exemples de constructions :

>>> ville2 = dict([('nom', 'bruxelles'), ('population', 174383)])
>>> ville2_completee = dict(ville2, annee=2011)
>>> ville3 = dict(zip(['annee', 'population', 'nom'], [2019, 1035000, 'berne']))

En compréhension

>>> points_visites = {(i, j):False for i in range(-1, 2) for j in range(2)}
>>> points_visites
{(-1, 0): False,
 (-1, 1): False,
 (0, 0): False,
 (0, 1): False,
 (1, 0): False,
 (1, 1): False}

Manipuler un dictionnaire

Accès aux valeurs

Comme pour les séquences, on utilisera l'opérateur crochet auquel on passe une clé, pour obtenir la valeur associée :

>>> ville = {'nom':'lyon', 'population':513275, 'annee':2015}
>>> ville['nom']
'lyon'

La méthode values() nous offre un objet itérable de toutes les valeurs du dictionnaire, que l'on peut parcourir par une boucle for ou transformer en list :

>>> list(ville.values())
['lyon', 513275, 2015]

Tenter d'accéder à une clé inexistante provoque une KeyError :

>>> ville['densite']
KeyError                                  Traceback (most recent call last)
<ipython-input-21-45d5e1ac4a54> in <module>
----> 1 ville['densite']

KeyError: 'densite'

Modifier un dictionnaire

Le dictionnaire est un objet modifiable. On peut donc changer la valeur associée à une clé :

>>> ville4 = {'nom':'lausanne', 'population':139720, 'annee':2019}
>>> ville4['annee'] = 2018

On peut ajouter des clés et des valeurs :

>>> ville4['pays'] = 'suisse'
>>> ville4
{'nom': 'lausanne', 'population': 139720, 'annee': 2018, 'pays': 'suisse'}
>>> ville4.update({'densite':3377, 'alt_min':372, 'alt_max':929})
>>> ville4
{'nom': 'lausanne',
 'population': 139720,
 'annee': 2018,
 'pays': 'suisse',
 'densite': 3377,
 'alt_min': 372,
 'alt_max': 929}

Récupérer une valeur via sa clé et supprimer la paire du dictionnaire :

>>> altitude = ville4.pop('alt_min')
>>> altitude += ville4.pop('alt_max')
>>> ville4
{'nom': 'lausanne',
 'population': 139720,
 'annee': 2018,
 'pays': 'suisse',
 'densite': 3377}
>>> ville4['alt'] = altitude // 2
>>> ville4
{'nom': 'lausanne',
 'population': 139720,
 'annee': 2018,
 'pays': 'suisse',
 'densite': 3377,
 'alt': 650}

Parcourir un dictionnaire

Le dict de Python est un itérable et peut donc à ce titre être utilisé avec une boucle for. Le parcours se fait sur les clés.

>>> anglais_francais = {'one':'un', 'two':'deux'}
>>> for word in anglais_francais:
        print(word)
one
two

Lors du parcours d'une séquence, l'ordre est celui des indices : 0, 1... Pour un dictionnaire, la question se pose. La réponse dépend de votre version de Python :

  • avant Python 3.7 : les clés ne sont pas ordonnées
  • à partir de Python 3.7 : l'ordre d'insertion ou de création des clés est préservée.

Toutefois, pour une initiation à la programmation il est plus sage de ne faire aucune hypothèse sur l'ordre des clés. Si un parcours suivant un ordre particulier doit être réalisé, il conviendra de créer une liste triée des clés au préalable. Pour cela, la méthode keys nous permet par exemple ceci :

>>> mini = {'c':['C', 'C++', 'CommonLisp'], 'a':['ADA'], 'p':['Python', 'Pascal']}
>>> cles_alphabetique = sorted(mini.keys())
>>> cles_alphabetique
['a', 'c', 'p']
Parcourir les valeurs

Nous l'avons vu, la méthode values offre un itérable sur les valeurs :

>>> for mot in anglais_francais.values():
        print(mot)
un
deux
Parcourir les paires

Enfin la méthode items donne les paires clé / valeur sous la forme de tuple :

>>> for word, mot in anglais_francais.items():
       print(f'{word} se dit {mot}')
one se dit un
two se dit deux

Tester l'appartenance

L'opérateur in comme pour les séquences teste l'appartenance. Pour un dictionnaire, ce sont les clés qui importent :

>>> au_frigo = {'pomme':10, 'orange':5, 'mangue':0}
>>> 'mangue' in au_frigo
True
>>> 10 in au_frigo
False

Le test d'appartenance est bien plus efficace avec un dictionnaire qu'avec une list ou un tuple. Si vous avez essayé le test avec la grand_liste de la section sur les tableaux, voyez la différence avec :

>>> grand_dico = {e:True for e in range(1000000)}
>>> -1 in grand_dico
False