defaultdict
: L'évolution du dictionnaire sans conditions
Il existe de nombreuses bibliothèques externes en Python, mais en comprenant bien la bibliothèque standard, vous pouvez écrire un code suffisamment puissant pour un usage pratique. Dans cet article, nous allons explorer en profondeur collections.defaultdict
.
Avec cet article, vous comprendrez clairement quand, pourquoi et comment utiliser defaultdict
au-delà d'une simple introduction conceptuelle.
Pour ceux qui se demandent sur la première classe de la série collections, Counter, je vous recommande de lire l'article précédent. Bibliothèque standard Python ① - collections.Counter
1. Concept de base : Qu'est-ce que defaultdict
?
defaultdict
est une sous-classe de dictionnaires (dict) qui sont inclus dans le module collections
de la bibliothèque standard de Python. Lorsque vous accédez à une clé qui n'existe pas dans un dictionnaire classique, une KeyError
se produit, mais avec defaultdict
, vous pouvez spécifier une fonction (fonction de fabrique) qui crée automatiquement une valeur par défaut, rendant votre code beaucoup plus propre et évitant les erreurs.
2. Utilisation de base
from collections import defaultdict
d = defaultdict(int)
d['apple'] += 1
print(d) # defaultdict(<class 'int'>, {'apple': 1})
Ici, int()
retourne 0
comme valeur par défaut. Lorsqu'on accède à la clé inexistant 'apple'
, il crée automatiquement 0
sans KeyError
puis exécute +1
.
3. Exemples de diverses valeurs par défaut
from collections import defaultdict
# Valeur par défaut : 0 (int)
counter = defaultdict(int)
counter['a'] += 1
print(counter) # defaultdict(<class 'int'>, {'a': 1})
# Valeur par défaut : liste vide
group = defaultdict(list)
group['fruit'].append('apple')
group['fruit'].append('banana')
print(group) # defaultdict(<class 'list'>, {'fruit': ['apple', 'banana']})
# Valeur par défaut : ensemble vide
unique_tags = defaultdict(set)
unique_tags['tags'].add('python')
unique_tags['tags'].add('coding')
print(unique_tags) # defaultdict(<class 'set'>, {'tags': {'python', 'coding'}})
# Valeur par défaut : valeur initiale personnalisée
fixed = defaultdict(lambda: 100)
print(fixed['unknown']) # 100
4. Exemples pratiques
1. Compter la fréquence des mots
words = ['apple', 'banana', 'apple', 'orange', 'banana']
counter = defaultdict(int)
for word in words:
counter[word] += 1
print(counter)
# defaultdict(<class 'int'>, {'apple': 2, 'banana': 2, 'orange': 1})
👉 Counter vs defaultdict
Pour compter la fréquence des mots, collections.Counter()
est plus spécialisé, et il est préférable de l'utiliser dans des cas nécessitant des statistiques ou une analyse de classement. Cependant, pour un simple comptage cumulatif, defaultdict(int)
peut également être utilisé de manière concise.
2. Organiser des logs par groupe
logs = [
('2024-01-01', 'INFO'),
('2024-01-01', 'ERROR'),
('2024-01-02', 'DEBUG'),
]
grouped = defaultdict(list)
for date, level in logs:
grouped[date].append(level)
print(grouped)
# defaultdict(<class 'list'>, {'2024-01-01': ['INFO', 'ERROR'], '2024-01-02': ['DEBUG']})
3. Organisation des tags uniques
entries = [
('post1', 'python'),
('post1', 'coding'),
('post1', 'python'),
]
tags = defaultdict(set)
for post, tag in entries:
tags[post].add(tag)
print(tags)
# defaultdict(<class 'set'>, {'post1': {'python', 'coding'}})
5. Points à surveiller
defaultdict
stocke un générateur de valeur par défaut en interne, donc lors de l'appel derepr()
, il peut apparaître différemment d'undict
classique.- Cela peut poser des problèmes lors de la sérialisation JSON. Il est plus sûr de le traiter après l'avoir transformé en
dict(d)
. - La valeur par défaut n'est créée que lors d'un accès via
[]
. Elle ne sera pas créée si vous utilisezget()
.
from collections import defaultdict
d = defaultdict(list)
print(d.get('missing')) # None
print(d['missing']) # []
6. Quand est-il bon à utiliser ? – 3 avantages décisifs de defaultdict
defaultdict
améliore simultanément la lisibilité, la maintenabilité et la sécurité dans des situations où vous utilisez fréquemment le modèle dict
+ condition
. Vous aurez trois occasions de vous dire : 'Ah, dans ce cas, mieux vaut utiliser defaultdict !'
6-1. Code d'agrégation sans condition pour compter/cumul
from collections import defaultdict
# Dictionnaire classique
counts = {}
for item in items:
if item not in counts:
counts[item] = 0
counts[item] += 1
# defaultdict
counts = defaultdict(int)
for item in items:
counts[item] += 1
✔ La disparition des conditions rend le code plus concis et réduit les possibilités d'erreur.
✔ Ceci est particulièrement adapté à l'analyse de logs et au comptage de mots dans des ensembles de données volumineux.
6-2. Remplacement de setdefault
lors de l'accumulation de listes/ensembles
from collections import defaultdict
# Dictionnaire classique
posts = {}
for tag, post in data:
if tag not in posts:
posts[tag] = []
posts[tag].append(post)
# defaultdict
posts = defaultdict(list)
for tag, post in data:
posts[tag].append(post)
✔ C'est beaucoup plus intuitif que setdefault()
et reste propre même dans une boucle.
✔ C'est une structure optimisée pour le groupement de données.
6-3. Automatisation de l'initialisation lors de la création de dictionnaires imbriqués
# Dictionnaire classique
matrix = {}
if 'x' not in matrix:
matrix['x'] = {}
matrix['x']['y'] = 10
# Imbrication avec defaultdict
matrix = defaultdict(lambda: defaultdict(int)) # Crée automatiquement defaultdict(int) à chaque fois qu'une clé est absente
matrix['x']['y'] += 10
✔ Vous pouvez facilement créer des structures de données imbriquées, ce qui est très avantageux pour les travaux sur des dictionnaires multidimensionnels.
✔ Cela est d'une grande utilité pour le data mining, le parsing et le stockage de structures en arbre.
lambda: defaultdict(int)
est structurée pour retournerdefaultdict(int)
chaque fois qu'une clé est manquante, générant automatiquement un dictionnaire imbriqué.
7. Conclusion
collections.defaultdict
peut sembler être une simple version extensible du dict
pour les débutants, mais à l'usage, vous réaliserez que c'est un outil structurel qui rend le code plus clair et plus sûr.
- Vous pouvez utiliser des dictionnaires sans craindre le
KeyError
. - Vous pouvez grouper et cumuler des données sans conditions.
- Vous pouvez composer intuitivement des dictionnaires imbriqués.
# Exemples de gestion avec defaultdict pour plus de stabilité et de clarté
salaries = defaultdict(int)
for dept, amount in records:
salaries[dept] += amount
Si vous pouvez prévenir les erreurs, améliorer la lisibilité et assurer la maintenabilité en une seule ligne de code,
defaultdict
n'est pas seulement une fonction pratique, mais un outil central dans la manière de penser en Python.
Le prochain sujet sera pathlib
.
Une façon moderne de traiter les fichiers et répertoires de manière orientée objet, utile pour débutants et intermédiaires. Les développeurs familiers avec os.path
seront ravis de constater à quel point c'est plus simple ! Restez à l'écoute pour le prochain épisode.
Add a New Comment