defaultdict
: de evolutie van een onvoorwaardelijke dictionary
Python heeft talloze externe bibliotheken, maar met alleen een goed begrip van de standaardbibliotheek kun je al krachtige code schrijven in de praktijk. In dit artikel gaan we dieper in op collections.defaultdict
.
Dit artikel helpt je niet alleen om het eenvoudige concept te begrijpen, maar ook om helder te krijgen wanneer, waarom en hoe je defaultdict
moet gebruiken.
Als je geïnteresseerd bent in de eerste in de collections
serie, de Counter-klasse, raad ik je aan om het vorige artikel te lezen.
Python Standaardbibliotheek ① - collections.Counter
1. Basisconcept: Wat is defaultdict
?
defaultdict
is een speciale subclass van dictionary (dict) die is opgenomen in de Python standaardbibliotheek collections
module. In een algemene dictionary ontstaat er een KeyError
wanneer je probeert toegang te krijgen tot een niet-bestaande sleutel, maar met defaultdict
kun je een functie (factory function) specificeren die automatisch een standaardwaarde genereert, waardoor je code veel cleaner wordt en fouten worden voorkomen.
2. Basisgebruik
from collections import defaultdict
d = defaultdict(int)
d['apple'] += 1
print(d) # defaultdict(<class 'int'>, {'apple': 1})
Hier retourneert int()
de standaardwaarde 0
. Wanneer je toegang probeert te krijgen tot de niet-bestaande sleutel 'apple'
, wordt er automatisch 0
gegenereerd zonder een KeyError
, waarna +1
wordt uitgevoerd.
3. Voorbeelden van verschillende standaardwaarden
from collections import defaultdict
# Standaardwaarde: 0 (int)
counter = defaultdict(int)
counter['a'] += 1
print(counter) # defaultdict(<class 'int'>, {'a': 1})
# Standaardwaarde: lege lijst
group = defaultdict(list)
group['fruit'].append('apple')
group['fruit'].append('banana')
print(group) # defaultdict(<class 'list'>, {'fruit': ['apple', 'banana']})
# Standaardwaarde: lege set
unique_tags = defaultdict(set)
unique_tags['tags'].add('python')
unique_tags['tags'].add('coding')
print(unique_tags) # defaultdict(<class 'set'>, {'tags': {'python', 'coding'}})
# Standaardwaarde: aangepaste initiële waarde
fixed = defaultdict(lambda: 100)
print(fixed['unknown']) # 100
4. Voorbeeld in de praktijk
1. Woordfrequentie tellen
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
Voor het tellen van woordfrequenties is collections.Counter()
beter gespecialiseerd, dus als je statistieken of ranglijsten nodig hebt, is het raadzaam om Counter
te gebruiken. Maar voor eenvoudige accumulaties zoals tellen kan defaultdict(int)
ook heel overzichtelijk worden gebruikt.
2. Logs per groep organiseren
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. Verwijderde tags organiseren
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. Let op
defaultdict
slaat intern de standaardwaarde-generator op, zodatrepr()
anders kan zijn dan die van een gewonedict
.- Er kunnen problemen optreden bij JSON-serialisatie. Het is veiliger om te converteren naar
dict(d)
en het daarna te verwerken. - De standaardwaarde wordt alleen gegenereerd bij toegang via
[]
. Wanneer jeget()
gebruikt, wordt deze niet gegenereerd.
from collections import defaultdict
d = defaultdict(list)
print(d.get('missing')) # None
print(d['missing']) # []
6. Wanneer is het nuttig? - 3 Beslissende voordelen van defaultdict
defaultdict
verhoogt de leesbaarheid, onderhoudbaarheid en veiligheid op locaties waar vaak de dict
+ voorwaardelijke instructies
patronen worden gebruikt. Je zult vooral de volgende 3 situaties herkennen waarin je denkt: 'Ja, dit is absoluut beter met defaultdict!'
6-1. Agregatiecode zonder voorwaarden voor tellen/accumuleren
from collections import defaultdict
# Gewone 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
✔ Door de voorwaarde te verwijderen wordt de code eenvoudiger en de kans op fouten kleiner.
✔ Het is vooral geschikt voor het analyseren van logs, het tellen van woorden en het verwerken van grote hoeveelheden gegevens.
6-2. Bij het accumuleren van lijsten/sets als vervanging van setdefault
from collections import defaultdict
# Gewone 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)
✔ Veel intuïtiever en netter binnen lussen dan setdefault()
.
✔ Het is geoptimaliseerd voor gegevensgroepering.
6-3. Automatisering van initialisatie bij geneste dictionaries
# Gewone dictionary
matrix = {}
if 'x' not in matrix:
matrix['x'] = {}
matrix['x']['y'] = 10
# Geneste defaultdict
matrix = defaultdict(lambda: defaultdict(int)) # Automatiseerde creatie van defaultdict(int) telkens een sleutel ontbreekt
matrix['x']['y'] += 10
✔ Het maken van geneste datastructuren wordt eenvoudig, wat zeer voordelig is voor multidimensionale dictionary-werkzaamheden.
✔ Het vertoont sterke voordelen bij data mining, parsing en opslag van boomstructuren.
lambda: defaultdict(int)
is intern gestructureerd om eendefaultdict(int)
te retourneren telkens wanneer een sleutel ontbreekt, waardoor automatisch de dictionaries genest worden aangemaakt.
7. Samenvatting
collections.defaultdict
kan voor beginners lijken op een eenvoudige uitbreiding van dict
, maar naarmate je het meer gebruikt, zul je merken dat het een structureel hulpmiddel is dat de code duidelijker en veiliger maakt.
- Je kunt dictionaries gebruiken zonder je zorgen te maken over
KeyError
. - Je kunt data groeperen en accumuleren zonder voorwaarden.
- Je kunt geneste dictionaries intuïtief opbouwen.
# Voorbeeld van betrouwbare en overzichtelijke verwerking met defaultdict
salaries = defaultdict(int)
for dept, amount in records:
salaries[dept] += amount
Als je met één regel code fouten kunt voorkomen + de leesbaarheid kunt verbeteren + onderhoudbaarheid kunt garanderen,
kan worden gesteld dat defaultdict
niet slechts een handig hulpmiddel is, maar de sleuteltool van een Python-denkwijze.
Het volgende onderwerp dat we zullen behandelen is pathlib
.
Een moderne manier om code voor bestand-/directorybeheer objectgeoriënteerd te maken, die nuttig is voor zowel beginners als gevorderden. Ontwikkelaars die gewend zijn aan os.path
zullen denken: "Wow! Dit is veel eenvoudiger dan os.path!" We kijken uit naar het volgende artikel.
댓글이 없습니다.