defaultdict
: Die Evolution des bedingungslosen Wörterbuchs
In Python gibt es zahlreiche externe Bibliotheken, aber allein mit dem Verständnis der Standardbibliothek können Sie bereits leistungsstarken Code für den praktischen Einsatz erstellen. In diesem Artikel werden wir uns eingehend mit collections.defaultdict
beschäftigen.
Durch diesen Artikel werden Sie über die einfache Konzeptvorstellung hinaus verstehen, wann, warum und wie Sie defaultdict
effektiv einsetzen können.
Wenn Sie an der ersten Klasse der collections
-Serie, der Counter
-Klasse interessiert sind, empfehle ich Ihnen, den vorherigen Artikel zu lesen:
Python Standardbibliothek ① - collections.Counter
1. Grundkonzept: Was ist defaultdict
?
defaultdict
ist eine spezielle Unterklasse des Dictionaries (dict), die im Python-Standardbibliotheksmodul collections
enthalten ist. Bei einem normalen Dictionary tritt ein KeyError
auf, wenn auf einen nicht vorhandenen Schlüssel zugegriffen wird, aber defaultdict
ermöglicht es, eine Funktion zum automatischen Erstellen von Standardwerten (Factory Function) anzugeben, dadurch wird der Code viel sauberer und Fehler werden vermieden.
2. Grundlegende Verwendung
from collections import defaultdict
d = defaultdict(int)
d['apple'] += 1
print(d) # defaultdict(<class 'int'>, {'apple': 1})
Hier gibt int()
0 als Standardwert zurück. Wenn auf den nicht existierenden Schlüssel 'apple'
zugegriffen wird, wird automatisch ohne KeyError
eine 0 erstellt, und danach wird +1
angewendet.
3. Verschiedene Beispiele für Standardwerte
from collections import defaultdict
# Standardwert: 0 (int)
counter = defaultdict(int)
counter['a'] += 1
print(counter) # defaultdict(<class 'int'>, {'a': 1})
# Standardwert: leere Liste
group = defaultdict(list)
group['fruit'].append('apple')
group['fruit'].append('banana')
print(group) # defaultdict(<class 'list'>, {'fruit': ['apple', 'banana']})
# Standardwert: leere Menge
unique_tags = defaultdict(set)
unique_tags['tags'].add('python')
unique_tags['tags'].add('coding')
print(unique_tags) # defaultdict(<class 'set'>, {'tags': {'python', 'coding'}})
# Standardwert: benutzerdefinierter Anfangswert
fixed = defaultdict(lambda: 100)
print(fixed['unknown']) # 100
4. Praktische Beispiele
1. Zählen der Wortfrequenzen
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
Das Zählen von Wortfrequenzen ist spezialisierter auf collections.Counter()
, daher ist es ratsam, Counter
bei statistischen oder Rankinganalysen zu verwenden. Bei einfachen Summierungen wie dem kumulativen Zählen kann jedoch auch defaultdict(int)
ausreichend klar verwendet werden.
2. Protokolle nach Gruppen ordnen
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. Aufbereitung von doppelten Tags
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. Hinweise
defaultdict
speichert intern den Standardwert-Erzeuger, sodass beimrepr()
ein anderes Format als bei einem normalendict
resultieren kann.- Dies könnte bei der JSON-Serialisierung zu Problemen führen. Es ist sicherer, dies mit
dict(d)
zu konvertieren und zu verarbeiten. - Der Standardwert wird nur bei Zugriff über
[]
erzeugt. Bei Zugriff überget()
wird er nicht erzeugt.
from collections import defaultdict
d = defaultdict(list)
print(d.get('missing')) # None
print(d['missing']) # []
6. Wann ist es nützlich? – Drei entscheidende Vorteile von defaultdict
defaultdict
verbessert dict
+ Bedingung
-Muster erheblich in Bezug auf Lesbarkeit, Wartbarkeit und Sicherheit. Besonders in den folgenden drei Situationen werden Sie denken: 'Ja, in diesem Fall sollte ich unbedingt defaultdict
verwenden!'
6-1. Aggregationscode ohne Bedingungen zählen/kumulieren
from collections import defaultdict
# Normales dict
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
✔ Die Bedingung entfällt, was den Code vereinfacht und das Fehlerrisiko verringert.
✔ Besonders geeignet für die Verarbeitung von großen Datenmengen, wie z.B. Protokollanalysen und Wortzählungen.
6-2. Ersetzen von setdefault
beim kumulierten Arbeiten mit Listen/Mengen
from collections import defaultdict
# Normales dict
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)
✔ Ist viel intuitiver als setdefault()
und sieht auch in Schleifen ordentlich aus.
✔ Optimierte Struktur zur Gruppierung von Daten.
6-3. Automatisierung der Initialisierung beim Erstellen von geschachtelten Dictionaries
# Normales Dictionary
matrix = {}
if 'x' not in matrix:
matrix['x'] = {}
matrix['x']['y'] = 10
# Geschachteltes defaultdict
matrix = defaultdict(lambda: defaultdict(int)) # Bei Nichtexistenz wird automatisch ein defaultdict(int) erzeugt
matrix['x']['y'] += 10
✔ Ermöglicht es, verschachtelte Datenstrukturen einfach zu erstellen, was für multidimensionale Dictionary-Arbeiten sehr vorteilhaft ist.
✔ Zeigt starke Vorteile beim Daten-Mining, Parsing und Speichern von Baustrukturen.
lambda: defaultdict(int)
ist so strukturiert, dass es bei Nichtexistenz der Schlüssel automatischdefaultdict(int)
zurückgibt, wodurch das Dictionary automatisch geschachtelt erzeugt wird.
7. Zusammenfassung
collections.defaultdict
mag auf den ersten Blick wie eine einfache Erweiterung von dict
erscheinen, aber je mehr Sie es verwenden, desto mehr spüren Sie, dass es ein strukturelles Werkzeug ist, das Ihren Code klarer und sicherer macht.
- Sie können Dictionaries verwenden, ohne sich um
KeyError
sorgen zu müssen. - Es ist möglich, Daten ohne Bedingungen zu gruppieren und zu akkumulieren.
- Verschachtelte Dictionaries können auf intuitive Weise erstellt werden.
# Beispiel für eine zuverlässige und einfache Verarbeitung mit defaultdict
salaries = defaultdict(int)
for dept, amount in records:
salaries[dept] += amount
Wenn Sie mit einer Zeile Code Fehlervermeidung, Lesbarkeit und Wartbarkeit erreichen können,
dann ist defaultdict
nicht nur eine praktische Funktion, sondern ein zentraler Bestandteil eines Python-gerechten Denkansatzes.
Das nächste Thema wird pathlib
sein.
Es handelt sich um einen modernen Ansatz, um den Umgang mit Dateien/Verzeichnissen objektorientiert zu gestalten, der sowohl für Anfänger als auch für Fortgeschrittene nützlich ist. Entwickler, die mit os.path
vertraut sind, werden denken: "Wow! Das ist viel einfacher als os.path!" Freuen Sie sich auf die nächste Folge.
Add a New Comment