Dictionaries#
(Klicken Sie hier für die englische Version dieser Seite)
Dictionaries allgemein#
Bei Dictionaries, auch als Hashmaps bekannt, handelt es sich um eine Datenstruktur mit welcher sich Schlüssel-Wert-Paare speichern lassen.
Wenn man möchte, kann man sich vorstellen, dass eine Liste ein Dictionary ist, wo die Indizes 0, 1, …, N
als Schlüssel benutzt werden.
Schlüssel#
Im Gegensatz zu einer gewöhnlicher Liste, werden hier nicht nur numerische Indizes 0, 1, …, N
zugelassen, sondern jegliche Datentypen, Datenstrukturen und Klassen solange sie unveränderlich (immutable) sind. Also nicht interne Werte ändern können ohne ein neues Objekt erstellen zu müssen.
Strings sind in Python etwa unveränderlich. Diesen Fakt kann man selbst überprüfen:
wort = "dictionary"
print(wort[0])
# --> "d"
wort[0] = "D"
# --> TypeError: 'str' object does not support item assignment
Hierbei bekommt man den Fehler, dass der Datentype str
(String) keine Wertzuweisungen erlaubt. Der Grund dafür ist, dass Strings unveränderlich sind.
Listen hingegen sind nicht unveränderlich, da man etwa mit append()
weitere Elemente hinzufügen kann.
liste = [1, 2, 3]
print(liste)
# --> [1, 2, 3]
liste.append(4)
print(liste)
# --> [1, 2, 3, 4]
Somit hat sich der Wert von liste
verändert ohne ein neues Objekt zuweisen zu müssen.
Jede als unveränderlich definiertes Objekt implementiert ebenfalls die __hash__()
Methode. Wenn man die Methode nicht explizit definiert, wird diese oft vererbt. Diese Methode nutzt Hashing um einem Objekt eine Identifikationsnummer zu geben. Bei Strings ist jene Funktion vorhanden, bei Listen jedoch nicht.
wort = "dictionary"
print(wort.__hash__())
# --> 4122803001462702718
liste = [1, 2, 3]
print(liste.__hash__())
# --> 'NoneType' object is not callable
# Die __hash__() Methode existiert bei der Liste nicht
Wenn man trotzdem etwas ähnliches wie eine Liste nutzen möchte, so gibt es den Datentyp “Tupel”, welches eine explizit unveränderliche Liste ist. Mehr Information dazu, gibt es in dem Kapitel zu Tupel.
Zusätzlich müssen die Schlüssel einzigartig sein. Alle Schlüssel brauchen jeweils einen eigenen Hashwert. Jedoch müssen die Schlüssel nicht alle vom selben Datentypen sein, solange die Bedingung der Unveränderlichkeit erfüllt ist.
Werte#
Im Gegensatz zu dem Schlüssel gibt es für den Wert keine Einschränkungen. Der Wert kann einen beliebigen Datentypen haben, sowohl veränderlich, unveränderlich, einzigartig als auch nicht einzigartig.
Erstellen eines Dictionaries#
Bei der Python Syntax werden geschweifte Klammern und Doppelpunkte genutzt um Dictionaries zu definieren. Die geschweiften Klammern definieren das Objekt selbst und die Schlüssel-Wert-Paare werden mit der Syntax Schlüssel: Wert
in dem Dictionary definiert. Mehrere Schlüssel-Wert-Paare werden mit einem Komma getrennt, wie bei einer Liste.
In dem folgenden Beispiel wird gezeigt, dass die Schlüssel und Werte jeweils auch verschiedene Datentypen haben können. Sowohl z.B. Ganzzahlen als auch Strings gleichzeitig.
ziffern = {
1: "Eins",
"Zwei": 2,
3: "Drei"
}
print(ziffern)
# --> {1: 'Eins', 'Zwei': 2, 3: 'Drei'}
Dictionaries selbst sind unveränderliche Datentypen. Das heißt auch, dass Dictionaries zwar als Wert in anderen Dictionaries genutzt werden können, selber aber nicht Schlüssel sein können. Geschachtelte Dictionaries sind sehr interessant, da man so verschachtelte Objekte darstellen kann. Für Interessierte: Stichwort JSON.
Es können nach Erstellung eines Dictionaries, noch Einträge hinzugefügt werden.
Die Syntax dafür ist Dictionaryname[Schlüssel] = Wert
.
ziffern = {
1: "Eins"
}
ziffern[2] = "Zwei"
print(ziffern)
# --> {1: 'Eins', 2: 'Zwei'}
Die Werte eines Schlüssels können auch nachträglich verändert werden.
ziffern = {
1: "Eins",
2: "Zwei"
}
ziffern[2] = "Two"
print(ziffern)
# --> {1: 'Eins', 2: 'Two'}
Wert eines Schlüssels auslesen und überschreiben#
Um den Wert für einen gegebenen Schlüssel auszulesen, gibt es primär zwei Methoden. Entweder man nutzt, wie oben gesehen, die Indexsyntax wie bei Listen, wo man den Schlüssel als Index angibt.
uebersetzung = {
"Eins": "One",
"Zwei": "Two"
}
print(uebersetzung["Eins"])
# --> "One"
oder man nutzt die dafür vorgesehene Methode Dictionaryname.get(Schlüssel)
.
uebersetzung = {
"Eins": "One",
"Zwei": "Two"
}
print(uebersetzung.get("Eins"))
# --> "One"
Welche davon sollte man nutzen?
Zugriff über den Index ist ähnlich wie der Zugriff über den Index bei einer Liste. Wenn der Index in dem Dictionary nicht vorhanden ist, bekommt man einen Fehler.
Bei der Methode Dictionaryname.get(Schlüssel)
erhält man jedoch den Rückgabewert None
wenn der Index nicht existiert. Da kann man zusätzlich definieren, was anstelle von None
zurückgegeben werden soll, wenn es für diesen Schlüssel (noch) keinen Eintrag gibt.
ziffern = {
1: "Eins",
2: "Zwei"
}
print(ziffern[3])
# --> KeyError: 3
print(ziffern.get(3))
# --> None
# Wenn es den Wert für Schlüssel 3 nicht gibt,
# soll "Nicht vorhanden" zurückgegeben werden.
print(ziffern.get(3, "Nicht vorhanden"))
# --> "Nicht vorhanden"
Dafür kann man mit der Dictionaryname.get(Schlüssel)
Methode nicht den Wert überschreiben.
uebersetzung = {
"Eins": "One",
"Zwei": "Two"
}
uebersetzung.get("Eins") = "Uno"
# --> SyntaxError: cannot assign to function call here.
Einfach gesagt, wird empfohlen Dictionaryname.get(Schlüssel)
zu nutzen wenn man nur den Wert haben möchte und Dictionaryname[Schlüssel]
wenn man den Wert überschreiben möchte. Man kann problemlos auch beides nutzen.
inventar = {
"Bananen": 5,
"Birnen": 3
}
inventar["Birnen"] = inventar.get("Birnen", 0) + 3
print(inventar.get("Birnen"))
# --> 6
# Zitronen gibt es davor nicht.
# Mit inventar.get("Zitronen", 0)
# wird für Zitronen der Wert 0 zurückgegeben,
# da diese nicht im Inventar vorhanden sind.
# Danach werden die 5 draufgerechnet.
inventar["Zitronen"] = inventar.get("Zitronen", 0) + 5
print(inventar.get("Zitronen"))
# --> 5
Alle vorhandenen Schlüssel und Werte in einem Dictionary ausgeben#
Wenn man ein Dictionary hat und z.B. durch alle Schlüssel, Werte, oder gleich den Schlüssel-Wert-Paare iterieren möchte, so gibt es die drei Methoden
Dictionaryname.keys()
, Dictionaryname.values()
, Dictionaryname.items()
. Die Rückgabewerte sind jeweils ähnlich wie eine Liste, aber technisch gesehen keine echte Liste. Man kann diese jedoch mit list()
explizit zu einer Liste casten.
schluessel = list(Dictionaryname.keys())
Dictionaryname.keys()
gibt alle vorhandenen Schlüssel zurück. Dictionaryname.values()
gibt alle vorhandenen Werte zurück. Dictionaryname.items()
gibt alle vorhandenen Schlüssel-Wert-Paare als eine “Liste” von Tupeln (unveränderliche Liste mit runden Klammern statt eckigen Klammern gekennzeichnet) zurück.
uebersetzung = {
"Eins": "One",
"Zwei": "Two"
}
print(list(uebersetzung.keys()))
# --> ["Eins", "Zwei"]
print(list(uebersetzung.values()))
# --> ["One", "Two"]
schluesselwertpaare = list(uebersetzung.items())
print(schluesselwertpaare)
# --> [("Eins", "One"), ("Zwei", "Two")]
for schluesselwertpaar in schluesselwertpaare:
schluessel = schluesselwertpaar[0]
wert = schluesselwertpaar[1]
Aufgabe#
Stellen Sie sich vor, dass Sie einen Text haben und zählen möchten wie oft einzelne Wörter vorkommen. Um die Komplexität zu verringern, sind alle Wörter kleingeschrieben und bereits getrennt in einer Liste vorgegeben. Satzzeichen wurden ebenfalls entfernt.
Der ursprüngliche Text ist dieser:
Katzen spielen gerne, Katzen schlafen viel. Hunde bellen laut, aber Hunde rennen schnell. Spielen macht Spaß!
worte = ["katzen", "spielen", "gerne", "katzen",
"schlafen", "viel", "hunde", "bellen",
"laut", "aber", "hunde", "rennen",
"schnell", "spielen", "macht", "spaß"]
haeufigkeiten = ...
# Wie oft kommt das Wort "spielen" vor?
print(...)
# Wie oft kommt das Wort "viel" vor?
print(...)
# Wieviele einzigartige Wörter gibt es?
print(...)
# Wieviele Wörter gibt es im Text?
# Versuchen Sie es bitte ohne len(worte)!
print(...)
Ellipsis
Ellipsis
Ellipsis
Ellipsis
Lösung
worte = ["katzen", "spielen", "gerne", "katzen",
"schlafen", "viel", "hunde", "bellen",
"laut", "aber", "hunde", "rennen",
"schnell", "spielen", "macht", "spaß"]
haeufigkeiten = {}
for wort in worte:
haeufigkeiten[wort] = haeufigkeiten.get(wort, 0) + 1
# Wie oft kommt das Wort "spielen" vor?
print(haeufigkeiten.get("spielen"))
# --> 2
# Wie oft kommt das Wort "viel" vor?
print(haeufigkeiten.get("viel"))
# --> 1
# Wieviele einzigartige Wörter gibt es?
print(len(haeufigkeiten.keys()))
# --> 13
# Wieviele Wörter gibt es insgesamt?
# Versuchen Sie es bitte ohne len(worte)!
print(sum(haeufigkeiten.values()))
# --> 16
Man kann durch alle Worte iterieren und für jedes Wort gucken wie oft man es davor schon gesehen hat (0 falls noch nicht gesehen). Dann erhöht man die Anzahl um 1.
Da die Schlüssel einzigartig sind, geben die Schlüssel an wie viele einzigartige Wörter es gibt. Wenn ein Wort mehrmals vorkommt, wird der Wert beim gleichen Schlüssel erhöht.
In dem Dictionary haeufigkeiten
wird gezählt wie oft ein jenes Wort vorkommt. Wenn man die Summe aller Werte ausrechnet, ist das Ergebnis die Gesamtanzahl an Wörtern.