Introduction

Pour manipuler un ensemble de données, il est possible d’utiliser des tableaux (cf type List). Cependant, cette approche montre ses limites lorsque les informations à manipuler sont structurées et hétérogènes, comme pour décrire une personne (nom, prénom, âge…) par exemple.

Problème sans dictionnaire

Pour gérer une liste de personnes, une solution connue consiste de créer un tableau par information ; exemple :

from typing import List

noms: List[str] = ["Tehei", "Tufari", "Li", "Müller"]
prenoms: List[str] = ["Hiria", "Manutea", "Wei", "Hans"]

for i in range(len(noms)):
    nom_complet = prenoms[i] + " " + noms[i]
    print("Personne " + str(i + 1) + " : " + nom_complet)

Cette méthode présente des inconvénients importants : si une personne est ajoutée au tableau des noms mais pas à celui des prénoms, les données ne sont plus synchronisées. De plus, l’ajout d’une caractéristique (l’âge par exemple) nécessiterait un troisième tableau…

Le problème est que les informations relatives à une seule entité sont réparties dans plusieurs variables.

Solution avec un dictionnaire

Les dictionnaires de Python (tableaux associatifs dans d’autres langages) sont des structures de données qui permettent de regrouper plusieurs caractéristiques (par exemple celles d’une personne : nom, prénom…) en une seule variable. Dans cet exemple, “nom” et “prenom” sont les clés qui permettent d’accéder aux différentes caractéristique :

from typing import Dict

personne1: Dict = {"nom": "Tehei", "prenom": "Hiria"}
print(personne1["prenom"] + " " + personne1["nom"])

Pour gérer plusieurs personnes, il suffit de créer un tableau de dictionnaires :

from typing import List, Dict

personnes: List[Dict] = [
    {"nom": "Tehei", "prenom": "Hiria"},
    {"nom": "Tufari", "prenom": "Manutea"},
    {"nom": "Li", "prenom": "Wei"},
    {"nom": "Müller", "prenom": "Hans"}
]

for i in range(len(personnes)):
    personne = personnes[i]
    nom_complet = personne["prenom"] + " " + personne["nom"]
    #ou: nom_complet = personne[i]["prenom"] + " " + personne[i]["nom"]
    print("Personne " + str(i + 1) + " : " + nom_complet)

Alors qu’un tableau (type List) représente une collection d’éléments homogènes, un dictionnaire (type Dict) est un objet structuré — constitué de plusieurs caractéristiques.

Le principal cas d’usage des dictionnaires est donc la gestion d’entités : un profil utilisateur, une fiche produit… La programmation orientée objet qui remplit également cet objectif sera vue ultérieurement.

Création et manipulation des données

Un dictionnaire permet de regrouper plusieurs caractéristiques d’une entité sous la formes de paires (clé, valeur). La clé correspond à une caractéristique (un champ / un attribut / une propriété). La syntaxe permettant de désigner une caractéristique utilise des crochets : nom_var_dict["nom_clé"].

Ce cours se limite aux clés de type str.

Création et initialisation

La création d’un dictionnaire consiste à initialiser cette structure de données pour y stocker un enregistrement. Il existe deux manières principales de le faire.

La première est de créer un dictionnaire vide, puis de le compléter ensuite en affectant des valeurs à des clés ; exemple :

from typing import Dict

personne: Dict = {}
print("Dictionnaire vide : " + str(personne))
personne["nom"] = "Tehei"
personne["prenom"] = "Hiria"
print("Dictionnaire rempli : " + str(personne))

La seconde méthode consiste à initialiser le dictionnaire directement avec une ou plusieurs paires de clés / valeurs :

  • les accolades {} définissent le début et la fin du dictionnaire ;
  • les caractéristiques sont déclarées sous la forme "nom_clé" : valeur ;
  • les paires sont séparées par des virgules.

Exemple :

from typing import Dict

personne: Dict = {"nom": "Tehei", "prenom": "Hiria"}
print("Dictionnaire initialisé : " + str(personne))

Accès à une valeur

La valeur associée à une clé peut être affectée à une variable, utilisée dans une expression, passée en paramètre à une fonction… exemple :

from typing import Dict

personne: Dict = {"nom": "Tehei", "prenom": "Hiria"}
nom_personne: str = personne["nom"]
print("Nom de la personne : " + nom_personne)
print("Prénom de la personne : " + personne["prenom"])

Si la clé n’existe pas, une erreur KeyError est déclenchée. La méthode get permet d’éviter ce problème et de renvoyer une valeur par défaut si une clé n’existe pas : dictionnaire.get("clé", valeur_par_defaut) ; exemple :

personne: Dict = {"nom": "Tehei", "prenom": "Hiria"}
print(personne["courriel"]) #déclenche une erreur
civilite = personne.get("civilite", "M/Mme")
print(civilite)
personne["civilite"] = "Mme"
civilite = personne.get("civilite", "M/Mme")
print(civilite)

Modification d’un élément

Si la clé existe déjà dans le dictionnaire, sa valeur est remplacée ; exemple :

from typing import Dict

personne: Dict = {"nom": "Tehei", "prenom": "Hiria"}
print("Nom avant modification : " + personne["nom"])
personne["nom"] = "Tehei-Ura"
print("Nom après modification : " + personne["nom"])

Ajout d’un élément

Si la clé spécifiée n’existe pas, elle est créée ; exemple :

from typing import Dict

personne: Dict = {"nom": "Tehei", "prenom": "Hiria"}
print("Dictionnaire avant ajout : " + str(personne))
personne["age"] = 30
print("Dictionnaire après ajout : " + str(personne))

Remarque : la syntaxe pour l’ajout et la modification est identique ; l’opération effectuée dépend de la présence ou de l’absence de la clé dans le dictionnaire.

Suppression d’un élément

Pour supprimer une caractéristique / une paire (clé, valeur), on utilise l’instruction del nom_var["nom_clé"] ; exemple :

from typing import Dict

personne: Dict = {"nom": "Tehei", "prenom": "Hiria", "age": 30}
print("Dictionnaire avant suppression : " + str(personne))
del personne["age"]
print("Dictionnaire après suppression : " + str(personne))

Parcours et extraction

Le parcours d’un dictionnaire est une opération essentielle qui permet d’accéder à l’ensemble de ses données. Python propose plusieurs manières d’itérer de parcourir un dictionnaire.

Parcours des valeurs

Pour itérer uniquement sur les données contenues dans le dictionnaire, sans se soucier de leurs clés, on utilise la méthode .values().

from typing import Dict

personne: Dict = {"nom": "Tehei", "prenom": "Hiria", "age": 30}
for valeur in personne.values():
    print("- " + str(valeur))

Parcours des clés

Pour obtenir la liste des clés d’un dictionnaire, on utilise la méthode .keys() ; la clé permet ensuite d’accéder à la valeur associée ; exemple :

from typing import Dict, Any #Any = n'importe quel type

personne: Dict = {"nom": "Tehei", "prenom": "Hiria", "age": 30}
for cle in personne.keys():
    valeur: Any = personne[cle]     #clé est une variable de type "str"
    print("- " + cle + " : " + str(valeur))

Remarque : str(valeur) ne serait pas nécessaire pour des chaînes de caractères (ici nom et prenom), mais est indispensable pour un nombre (ici age) ; l’utiliser systématiquement (normalisation) ne pose pas de problème.

Parcours des paires (clé, valeur)

La méthode la plus complète et la plus courante est de parcourir le dictionnaire en récupérant simultanément la clé et sa valeur associée. On utilise pour cela la méthode .items() ; exemple :

from typing import Dict

personne: Dict = {"nom": "Tehei", "prenom": "Hiria", "age": 30}
for cle, valeur in personne.items():
    print("- " + cle + ": " + str(valeur))

Remarque : la méthode items renvoie une liste (tableau) de tuples : la clé et la valeur ; ce mécanisme est propre à Python. Pour l’expérimenter (approfondissement) :

from typing import Dict

personne: Dict = {"nom": "Tehei", "prenom": "Hiria", "age": 30}
print("Tableau des tuples : " + str(personne.items()))

items = list(personne.items())  #nécessaire pour accéder par indice
tuple = items[0]
print("Premier tuple clé / valeur : " + str(tuple))
key, value = items[0]           #syntaxe particulière à Python
print("\nClé : " + key + "\nValeur : " + str(value))
key = tuple[0]
value = tuple[1]
print("\nClé : " + key + "\nValeur : " + str(value))

Fonctions et méthodes utiles

Test d’appartenance d’une clé

Pour vérifier de manière sécurisée si un attribut (une clé) existe dans un enregistrement, on utilise l’opérateur in ; exemple :

from typing import Dict
from random import randint

personne: Dict = {"nom": "Tehei", "prenom": "Hiria", "age": 30}
if randint(0, 1) == 1: #une chance sur deux
    personne["email"] = "hiria@tehei.pf"

if "email" in personne:
    print("Email : " + personne["email"])
else:
    print("La clé \"email\" n'existe pas.")

Vider un dictionnaire

La méthode .clear() permet d’effacer le contenu d’un dictionnaire ; exemple :

from typing import Dict

personne: Dict = {"nom": "Tehei", "prenom": "Hiria", "age": 30}
print("Dictionnaire avant clear : " + str(personne))
personne.clear()
print("\nDictionnaire après clear : " + str(personne))

Application : gestion d’une collection

Les dictionnaires sont souvent utilisés au sein de tableaux : List|Dict[…]], pour gérer des collections d’entités, pour parcourir les enregistrements d’une base de données ou d’un fichier CSV.

Exemple : l’application suivante gère une collection de personnes. Elle est constituée de deux fonctions et d’un programme principal.

Fonction de saisie

Cette fonction invite l’utilisateur à saisir les informations (nom, prénom, âge) de plusieurs personnes. La saisie se termine lorsque l’utilisateur entre un nom vide. La fonction retourne ensuite la collection complète des personnes saisies.

def saisir_personnes() -> List[Dict]:
    """
    Saisit une liste de personnes et la retourne.
    @return la collection de personnes
    """
    personnes: List[Dict] = []
    continuer: bool = True
    while continuer:
        nom: str = input("Nom (<Entrée> pour terminer) : ")
        if nom == "":
            continuer = False
        else:
            prenom: str = input("Prénom : ")
            age: int = int(input("Âge : "))
            p: Dict = {"nom": nom, "prenom": prenom, "age": age}
            personnes.append(p)

    return personnes

Fonction d’affichage

Cette fonction prend une collection de personnes en paramètre et affiche les attributs de chaque enregistrement.

def afficher_personnes(collection: List[Dict]) -> None:
    """
    Affiche une liste de personnes de manière formatée.
    @param collection liste des personnes
    """
    for personne in collection:
        for cle, valeur in personne.items():
            print("- " + cle + ": " + str(valeur))
        print("\n")

Programme principal

Le programme principal utilise les deux fonctions.

from typing import List, Dict

#fonctions saisir_personnes et afficher_personnes

if __name__ == "__main__":
    liste_des_personnes: List[Dict] = saisir_personnes()
    afficher_personnes(liste_des_personnes)