Comment et quand utiliser Defaultdict en Python ?

Photo of author

By pierre



Ce guide pratique vous initiera à l’utilisation de `defaultdict`, un outil puissant du module `collections` de Python, conçu pour une gestion plus efficace des erreurs de clé (KeyErrors) lors de la manipulation de dictionnaires.

En Python, le dictionnaire est une structure de données fondamentale qui organise les informations en paires clé-valeur. Les clés servent d’accès pour récupérer les valeurs associées.

Cependant, lors de l’utilisation de plusieurs dictionnaires dans vos scripts Python, qui peuvent être modifiés au cours de l’exécution du programme, les erreurs de clé (KeyErrors) sont courantes. Il existe diverses méthodes pour les gérer.

Ce tutoriel vous permettra de comprendre :

  • La nature des KeyErrors et les circonstances de leur apparition.
  • Les différentes stratégies pour gérer ces erreurs.
  • Comment `defaultdict`, une sous-classe héritant de la classe `dict` standard, peut faciliter la gestion des clés manquantes.

Commençons sans tarder !

Que sont les KeyErrors en Python ?

Lors de la création d’un dictionnaire en Python, certaines règles fondamentales doivent être respectées :

  • Chaque clé doit être unique, sans doublons.
  • Si vous utilisez une séquence existante comme clés, il est préférable d’utiliser une collection immuable, comme un tuple.

Une clé n’est valide que si elle existe dans le dictionnaire. Tenter d’accéder à une clé inexistante déclenchera une KeyError.

Considérez le dictionnaire suivant, `books_authors`, où les titres de livres sont les clés et les noms d’auteurs les valeurs.

Vous pouvez reproduire les exemples de ce tutoriel directement dans un environnement REPL Python.

books_authors = {
    'Deep Work':'Cal Newport',
    'Hyperfocus':'Chris Bailey',
    'Pivot':'Jenny Blake',
    'The Happiness Equation':'Neil Pasricha'
}

Vous pouvez accéder au nom de l’auteur en utilisant le titre du livre (la clé) :

books_authors['Hyperfocus']
'Chris Bailey'

Pour afficher l’ensemble des paires clé-valeur, utilisez la méthode `items()` sur l’objet dictionnaire, comme ci-dessous :

for book,author in books_authors.items():
  print(f"'{book}' par {author}")
'Deep Work' par Cal Newport
'Hyperfocus' par Chris Bailey
'Pivot' par Jenny Blake
'The Happiness Equation' par Neil Pasricha

Tenter d’accéder à la valeur d’une clé qui n’existe pas dans le dictionnaire entraînera une KeyError. C’est le cas pour les clés ‘Grit’ et ‘clé inexistante’ dans les exemples suivants :

books_authors['Grit']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-6-e1a4486f5ced> in <module>
----> 1 books_authors['Grit']

KeyError: 'Grit'
books_authors['non-existent-key']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-7-a3efd56f69e5> in <module>
----> 1 books_authors['non-existent-key']

KeyError: 'non-existent-key'

Comment gérer les KeyErrors en Python ?

Plusieurs solutions existent, que nous allons examiner dans la section suivante.

Comment gérer les erreurs de clé en Python

Nous allons explorer différentes méthodes pour gérer les KeyErrors :

  • Les instructions conditionnelles `if-else`.
  • Les blocs `try-except`.
  • La méthode `.get()` des dictionnaires.

#1. Utilisation des instructions conditionnelles If-Else

L’une des manières les plus simples de gérer les KeyErrors est d’utiliser les instructions conditionnelles `if-else`.

En Python, la structure générale d’une instruction `if-else` est la suivante :

 if condition:
 	# exécuter ce bloc si la condition est vraie
 else:
    # exécuter ce bloc si la condition est fausse
  • Si la `condition` est vraie (`True`), le code du bloc `if` est exécuté.
  • Si la `condition` est fausse (`False`), le code du bloc `else` est exécuté.

Dans cet exemple, la condition est de vérifier si la clé est présente dans le dictionnaire.

Si la clé est présente, l’opérateur `in` renverra `True`, et le code du bloc `if` affichera la valeur correspondante.

key = 'The Happiness Equation'
if key in books_authors:
  print(books_authors[key])
else:
  print('Désolé, cette clé n\'existe pas !')

# Output
# Neil Pasricha

Si la clé n’est pas présente, l’opérateur `in` renverra `False`, et le bloc `else` sera exécuté, affichant un message indiquant que la clé est absente.

key = 'non-existent-key'
if key in books_authors:
  print(books_authors[key])
else:
  print('Désolé, cette clé n\'existe pas !')

# Output
# Désolé, cette clé n'existe pas !

#2. Utilisation des instructions Try-Except

Une autre approche courante consiste à utiliser les blocs `try-except` pour gérer les KeyErrors.

Observez le code suivant :

key = 'non-existent-key'
try:
  print(books_authors[key])
except KeyError:
  print('Désolé, cette clé n\'existe pas !')
  • Le bloc `try` tente de récupérer la valeur associée à la clé fournie.
  • Si la clé est inexistante, l’interpréteur Python lèvera une KeyError, qui sera traitée comme une exception dans le bloc `except`.

#3. Utilisation de la méthode .get()

Python offre la méthode `.get()` intégrée aux dictionnaires, spécialement conçue pour gérer les clés manquantes.

La syntaxe générale de la méthode `.get()` est `dict.get(key, default_value)`, où `dict` est un objet dictionnaire valide en Python.

– Si la clé est présente dans le dictionnaire, la méthode `.get()` retourne la valeur correspondante.
– Sinon, elle retourne la valeur `default_value` fournie.

Dans cet exemple, `keys` est une liste de clés dont on souhaite obtenir les valeurs. Nous parcourons la liste et utilisons `.get()` pour récupérer les valeurs correspondantes du dictionnaire `books_authors`.

Nous avons utilisé `.get()` avec `’N’existe pas’` comme valeur par défaut.

keys = ['Grit','Hyperfocus','Make Time','Deep Work']
for key in keys:
  print(books_authors.get(key,'N\'existe pas'))

Dans ce code :

  • Pour les clés existantes dans `books_authors`, la méthode `.get()` retourne les valeurs correspondantes.
  • Pour les clés absentes, ‘Grit’ et ‘Make Time’ dans ce cas, `.get()` renvoie la valeur par défaut `’N’existe pas’`.
# Output

N'existe pas
Chris Bailey
N'existe pas
Cal Newport

Toutes les méthodes présentées gèrent les erreurs de clé, mais elles peuvent être verbeuses et nécessitent une gestion explicite des clés manquantes. `defaultdict` offre une approche plus simple et élégante.

Defaultdict en Python

`defaultdict` est une sous-classe de la classe `dict`, héritant de son comportement. Il gère les clés manquantes de manière native.

Ce type de données est inclus dans le module `collections` de la bibliothèque standard de Python.

Vous devez l’importer dans votre environnement de travail :

from collections import defaultdict

La syntaxe générale d’utilisation de `defaultdict` est :

defaultdict(default_factory)

Vous pouvez spécifier un appelable comme `int`, `float`, ou `list` comme argument `default_factory`. Si `default_factory` n’est pas spécifié, sa valeur par défaut est `None`.

Lorsque vous accédez à une clé inexistante, la méthode `__missing__()` est appelée. Elle déduit la valeur par défaut de `default_factory` et la retourne.

En résumé :

  • Un `defaultdict` retourne la valeur par défaut si une clé n’existe pas.
  • Il ajoute également cette nouvelle paire clé-valeur au dictionnaire, que vous pourrez ensuite modifier.

Exemples Python Defaultdict

Examinons quelques exemples pour comprendre le fonctionnement de `defaultdict`.

Defaultdict avec une valeur entière par défaut

Commençons par importer `defaultdict` du module `collections`.

from collections import defaultdict
import random

Créons un `defaultdict` nommé `prices`.

prices = defaultdict(int)

Nous remplissons ce dictionnaire en utilisant les noms de fruits comme clés, et des prix aléatoires de la liste `price_list` comme valeurs.

price_list = [10,23,12,19,5]
fruits = ['apple','strawberry','pomegranate','blueberry']

for fruit in fruits:
  prices[fruit] = random.choice(price_list)

Examinons les paires clé-valeur du `defaultdict` `prices`.

print(prices.items())
dict_items([('apple', 12), ('blueberry', 19), ('pomegranate', 5), ('strawberry', 10)])

Comme avec un dictionnaire classique, vous pouvez accéder aux valeurs avec les clés correspondantes :

prices['apple']
# 12

Tentons maintenant d’accéder au prix d’un fruit inexistant, par exemple, ‘orange’. Il retourne la valeur par défaut, 0.

prices['orange']
# 0

En affichant le dictionnaire, on constate que la nouvelle clé ‘orange’ a été ajoutée avec la valeur par défaut 0.

print(prices.items())
dict_items([('apple', 12), ('blueberry', 19), ('pomegranate', 5), ('strawberry', 10), ('orange', 0)])

Defaultdict avec une liste comme valeur par défaut

Définissons `students_majors` comme un `defaultdict` dont les valeurs sont des listes. Les clés seront les noms des filières universitaires, et les valeurs les listes d’étudiants inscrits dans chacune d’elles.

from collections import defaultdict
students_majors = defaultdict(list)

En tentant d’accéder à la liste des étudiants en ‘Economie’, `defaultdict` retourne une liste vide, sans erreur !

students_majors['Economics']
# []

Une liste vide est maintenant associée à la clé ‘Economie’. Nous pouvons ajouter des éléments à cette liste en utilisant la méthode `.append()`.

students_majors['Economics'].append('Alex')

Une entrée pour ‘Economie’ a été créée dans `students_majors`.

print(students_majors)
defaultdict(<class 'list'>, {'Economics': ['Alex']})

Vous pouvez ajouter d’autres étudiants à la liste, créer de nouvelles filières et bien plus encore !

students_majors['Economics'].append('Bob')
students_majors['Math'].append('Laura')
print(students_majors)
defaultdict(<class 'list'>, {'Economics': ['Alex', 'Bob'], 'Math': ['Laura']})

Conclusion

J’espère que ce tutoriel vous a aidé à comprendre le fonctionnement et l’utilité de `defaultdict` en Python. Après avoir testé les exemples, vous pouvez envisager d’utiliser `defaultdict` comme structure de données privilégiée dans vos projets si nécessaire.

Voici un résumé des notions abordées :

  • Les KeyErrors sont fréquentes lors de l’utilisation de dictionnaires.
  • Plusieurs méthodes permettent de gérer ces erreurs : instructions conditionnelles, blocs `try-except`, méthode `.get()`, mais `defaultdict` du module `collections` simplifie grandement ce processus.
  • Vous pouvez utiliser `defaultdict(default_factory)`, où `default_factory` est un appelable valide.
  • Lorsqu’une clé est absente, une valeur par défaut, déduite de `default_factory`, est ajoutée au `defaultdict` avec la clé correspondante.

Pour aller plus loin, consultez le tutoriel sur la fonction `map` de Python.