Étendre les dictionnaires Python avec la librairie collections
- 2021-05-04
- Publié par : Christophe DELEUZE
- Catégorie : Python
Aujourd’hui, je vous propose de découvrir avec moi deux alternatives au dictionnaire utilisé par défaut en Python. Pour cela, nous allons utiliser le package collections qui est fourni en standard avec Python. Les deux alternatives vont nous permettre d’enrichir et d’adapter l’usage que vous avez des dictionnaires.
La première alternative que nous allons voir ensemble sera defaultdict et la seconde Counter.
Les valeurs par défaut des dictionnaires
Prenons l’exemple d’une liste dont nous souhaiterions connaître le nombre de doublons :
nombres = [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1,
0, 0, 8, 7, 9, 3, 3, 2, 1, 1, 0]
Nous avons une liste de nombres et nous voulons trouver le nombre d’occurrences de chaque nombre dans la liste.
Une façon de faire serait d’utiliser, par exemple, un dictionnaire avec des clés contenant tous les nombres possibles et d’incrémenter leur valeur en fonction du nombre d’occurrences trouvées dans la liste.
dictionnaire = {}
for nombre in nombres :
if nombre not in dictionnaire :
dictionnaire[nombre] = 0
dictionnaire[nombre] += 1
dictionnaire
Le résultat suivant démontre que nous avons réussi à compter correctement les éléments de la liste :
{1: 4, 2: 3, 3: 4, 4: 2, 5: 2, 6: 1, 0: 3, 8: 1, 7: 1, 9: 1}
Toutefois, faites très attention à l’extrait de code ci-dessous :
if nombre not in dictionnaire :
dictionnaire[nombre] = 0
Notez que, préalablement à l’incrémentation, nous devons vérifier si la valeur à compter existe déjà dans le dictionnaire. Si elle n’existe pas, nous devons l’initialiser. Sans ses deux étapes préalables, une erreur aurait été levée nous signifiant que la clé n’existe pas dans le dictionnaire :
>>> dictionnaire[10]
Traceback (most recent call last):
File "", line 1, in
KeyError: 10
Maintenant, nous pouvons améliorer ce code en s’aidant de la librairie collections qui va nous permettre de modifier le comportement du dictionnaire, notamment grâce à defaultdict.
Gérer les valeurs par défaut des dictionnaires avec defaultdict
defaultdict est un dictionnaire qui gère nativement les valeurs par défaut. Il est disponible dans le package collections.
Préalablement à l’utilisation de defaultdict, il vous faudra lui fournir une fonction qui indiquera au dictionnaire quelle valeur attribuer à une clé si celle-ci est inexistante au moment de l’attribution de la valeur. Il n’y aura donc plus d’erreur du type KeyError comme pour les dictionnaires réguliers. Cependant, à chaque fois que vous essayerez d’accéder à la valeur d’une clé ou d’attribuer une valeur à une clé qui n’existe pas, celle-ci sera automatiquement créée avec la valeur par défaut spécifiée dans la fonction.
Voici le code avec la fonction qui attribue la valeur par défaut :
from collections import defaultdict
def default_value():
return "Pas encore présente"
dictionnaire = defaultdict(default_value)
Attention, defaultdict prend un argument obligatoire : le nom de la fonction qui renvoie la valeur par défaut.
Attribuons maintenant les valeurs dans notre defaultdict :
dictionnaire["chat"] = 2
dictionnaire["chien"] = 4
Essayons d’appeler ces clés et d’obtenir leurs valeurs correspondantes :
>>> dictionnaire["chat"]
2
>>> dictionnaire["chien"]
4
Jusqu’à présent, nous voyons que ce n’est pas différent d’un dictionnaire ordinaire.
Toutefois, si nous recherchons une clé qui n’a pas été attribué :
>>> dictionnaire["cochon"]
Pas encore présent
Comme prévu, la valeur Pas encore présent associée à la clé "cochon" nous est retournée. Si nous imprimons le contenu de notre dictionnaire, vous remarquerez que la valeur "cochon" a bien été créée dans le dictionnaire :
{'chat': 2, 'chien': 4, 'cochon': 'Pas encore présent'}
Pour finir, il n’est pas nécessaire d’avoir une fonction telle que de default_value. Nous pouvons donc la transformer en fonction anonyme lambda que nous n’utiliserons qu’une seule fois.
dictionnaire = defaultdict(lambda: "Pas encore présent")
Enfin, dans le cadre d’une valeur par défaut qui serait un numérique, on pourra même utiliser l’un des raccourcis suivant pour simplifier encore le code :
defaultdict(lambda: 0)
ou
defaultdict(int)
compter avec Counter
Notre second et dernier candidat de la journée que nous allons découvrir ensemble est Counter. Sans chichi et comme son nom l’indique, Counter compte et il le fait très bien.
Il compte les caractères des chaines de caractères :
from collections import Counter
C1 = Counter("abcdeab")
>>> C1
Counter({'a': 2, 'b': 2, 'c': 1, 'd': 1, 'e': 1})
Il sait aussi très bien dénombrer les éléments des listes :
from collections import Counter
C2 = Counter(['c', 'd', 'c', 'e', 'a', 'b'])
>>> C2
Counter({'a': 1, 'b': 1, 'c': 2, 'd': 2, 'e': 1})
Pour finir, on peut même faire de l’arithmétique avec :
#Combinaison
>>> C1 + C2
Counter({'a': 3, 'b': 3, 'c': 3, 'd': 2, 'e': 2})
# Soustraction
>>> C1 - C2
Counter({'a': 1, 'b': 1})
# Intersection (Récupère les minimums positifs)
>>> C1 & C2
Counter({'a': 1, 'b': 1, 'c': 1, 'd': 1, 'e': 1})
# Union (Récupère les maximums)
>>> C1 | C2
Counter({'a': 2, 'b': 2, 'c': 2, 'd': 1, 'e': 1})
Alors si c’est aussi simple de s’en servir, pourquoi s’en priver ?
Le mot de la fin
Comme vous pouvez le voir, defaultdict s’est avéré être une alternative utile aux dictionnaires, en particulier lorsqu’il s’agit d’accumuler des valeurs. De la même façon, Counter trouve son utilité pour compter tout et n’importe quoi.
Les essayer, ce sont les adopter ! N’hésitez pas à les tester par vous-même dans l’interpréteur interactif et si vous avez la moindre question, les commentaires sont là pour ça.