14.9. Wörterbücher - dict#
Die letzte built-in Datenstruktur, welche wir besprechen, sind die sogenannten Wörterbücher (engl. Dictionary) dict
.
In anderen Programmiersprachen, wie z.B. Java
spricht man stattdessen auch von Hashtables oder Hashmaps.
Sie sind neben den Listen list
die zweitwichtigste Datenstruktur in Python
.
Zwar ist ihr Anwendungsgebiet ein anderes doch sind sie ähnlich wie Mengen set
realisiert.
Wörterbücher sind veränderlich (engl. mutable).
Wir können sie uns als zweispaltige Tabelle vorstellen.
Eine Spalte beinhaltet die eindeutigen sog. Schlüssel key
s und die andere Spalte enthält die sog. Werte value
s.
Jede Zeile ist ein Tupel tuple
aus key
und value
.
Da die Schlüssel im Sinne der Gleichheit eindeutig sind, kann die Spalte aus key
s als Menge set
an Schlüsseln angesehen werden.
Die Werte müssen hingegen nicht eindeutig sein.
Sind Sie wie ich ein Freund der Mathematik, so realisiert ein Wörterbücher dict
eine (mathematische) Funktion:
wobei \(K\) die endliche Menge der Schlüssel ist.
Es kann durchaus zwei Schlüssel geben, die auf den gleichen Wert value
verweisen, doch müssen die Schlüssel eindeutig sein!
Wie bei den Mengen, gilt für die Schlüssel, dass diese aus unveränderlichen Datentypen bestehen müssen. Das hat die gleichen Gründe wie in Abschnitt Mengen angesprochen. Deshalb eigenen sich zum Beispiel Zahlen, Zeichenketten, Fließkommazahlen oder Tupel – die unveränderliche Datentypen enthalten – als Schlüssel.
Identisch zu Mengen, können wir extrem schnell testen ob es einen bestimmten Eintrag im Wörterbücher für einen bestimmten Schlüssel gibt.
Das folgt aus der Eigenschaft der Mengen.
Doch anders als bei Mengen set
, identifizieren wir damit nicht nur den Schlüssel key
der Menge \(K\), sondern auch dessen Wert value
aus \(V\).
Wir nutzten die schnelle Adressierung bzw. den schnellen Zugriff um auf veränderliche Werte zugreifen zu können.
14.9.1. Erstellung#
Ein Wörterbuch dict
erzeugen Sie ebenfalls durch den Einsatz der geschweiften Klammern, doch besteht jeder Eintrag aus einem Tupel (key, value)
geschrieben als: key: value
.
Zum Beispiel könnten wir ein Wörterbuch students
erstellen für welches die eindeutige Matrikelnummer die Schlüssel \(K\) und die Nachnamen die Werte \(V\) sind.
students = {123451: 'Huber', 123451: 'Langer', 213131: 'Schmidt', 4131129: 'Langer'}
students
{123451: 'Langer', 213131: 'Schmidt', 4131129: 'Langer'}
Wir können ein Wörterbuch durch die Funktion dict()
aus einer Liste von Tupeln konstruieren:
students = dict([(123451, 'Huber'), (123451, 'Langer'), (213131, 'Schmidt'), (4131129, 'Langer')])
students
{123451: 'Langer', 213131: 'Schmidt', 4131129: 'Langer'}
Sofern Ihre Schlüssel Zeichenketten str
sind, erlaubt uns Python
auch die Argumentschreibweise zu verwenden:
rectangle = dict(shape='rectangle', x=0.0, y=1.0, width=10, height=20)
print(rectangle)
{'shape': 'rectangle', 'x': 0.0, 'y': 1.0, 'width': 10, 'height': 20}
14.9.2. Zugriff#
Im Unterschied zu Mengen können wir auf die Werte value
eines Wörterbuchs durch den passenden Schlüssel key
zugreifen.
Auch hierzu verwenden wir die eckigen Klammern.
dictionary[key]
ergibt den value
für den Schlüssel key
des Wörterbuchs.
students = {123451: 'Huber', 123451: 'Langer', 213131: 'Schmidt', 4131129: 'Langer'}
print(f' key = {123451}, value = {students[123451]}')
print(f' key = {4131129}, value = {students[4131129]}')
print(f' key = {213131}, value = {students[213131]}')
key = 123451, value = Langer
key = 4131129, value = Langer
key = 213131, value = Schmidt
Gibt es den Schlüssel nicht im Wörterbuch, so erhalten wir einen Fehler beim Zugriff.
print(f' key = {00000}, value = {students[00000]}')
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[5], line 1
----> 1 print(f' key = {00000}, value = {students[00000]}')
KeyError: 0
14.9.3. Veränderung#
Folgender Ausdruck hat eine von zwei möglichen Bedeutungen.
students = dict([(123451, 'Huber'), (123451, 'Langer'), (213131, 'Schmidt'), (4131129, 'Langer')])
students[123133] = 'Fischer'
students
{123451: 'Langer', 213131: 'Schmidt', 4131129: 'Langer', 123133: 'Fischer'}
In unserem Fall, fügen wir in das Wörterbuch students
ein neues Tupel (123133, 'Fischer')
ein.
Existiert der Schlüssen, hier 123133
, so verändern wir den damit identifizierten Eintrag:
students[123133] = 'Alberto'
students
{123451: 'Langer', 213131: 'Schmidt', 4131129: 'Langer', 123133: 'Alberto'}
In den meisten Fällen möchte man genau das, einen Eintrag verändern oder neu einfügen wenn er noch nicht existiert. Möchten Sie jedoch einen Eintrag nur verändern und nicht einfügen falls er nicht existiert, so müssen Sie zuvor testen ob er existiert:
# no insertion but a change
if 123133 in students:
students[123133] = 'Hamilton'
print(students)
# no insertion and no change
if -131331 in students:
students[-131331] = 'Hamilton'
print(students)
{123451: 'Langer', 213131: 'Schmidt', 4131129: 'Langer', 123133: 'Hamilton'}
{123451: 'Langer', 213131: 'Schmidt', 4131129: 'Langer', 123133: 'Hamilton'}
Wir testen in diesem Code ob der Schlüssel sich im Wörterbuch befindet.
Um zu testen ob ein Tupel (key, value)
sich im Wörterbuch befindet müssen Sie
testen ob sich
key
im Wörterbuch befindet undob
dictionary[key] == value
gilt.
# no insertion but a change
print(123133 in students and students[123133] == 'Hamilton')
print(123133 in students and students[123133] == 'Schmidt')
print(-111111 in students and students[-111111] == 'Schmidt')
True
False
False
Um ein Tupel aus dem Wörterbuch zu löschen verwenden wir erneut die built-in-Operation del
:
# no insertion but a change
print(123133 in students and students[123133] == 'Hamilton')
del students[123133]
print(123133 in students and students[123133] == 'Hamilton')
True
False
14.9.4. Ansichten#
Wir könne uns auch alle Schlüssel und Werte eines Wörterbuchs holen.
Durch dictionary.keys()
erhalten wir die Schlüssel, durch dictionary.values()
die Werte, und durch dictionary.items()
beide Spalten (als Liste von Tupeln):
students = dict([(123451, 'Huber'), (123451, 'Langer'), (213131, 'Schmidt'), (4131129, 'Langer')])
print(f'dictionary: {students}\n')
print(f'key: {students.keys()}')
print(f'values: {students.values()}')
print(f'items: {students.items()}')
dictionary: {123451: 'Langer', 213131: 'Schmidt', 4131129: 'Langer'}
key: dict_keys([123451, 213131, 4131129])
values: dict_values(['Langer', 'Schmidt', 'Langer'])
items: dict_items([(123451, 'Langer'), (213131, 'Schmidt'), (4131129, 'Langer')])
Es scheint so als wären dies alles Listen list
, doch das ist nicht korrekt.
Zwar werden Sie wie Listen ausgegeben, doch sind sie unveränderlich.
students = dict([(123451, 'Huber'), (123451, 'Langer'), (213131, 'Schmidt'), (4131129, 'Langer')])
values = students.values()
values[0] = 'Test'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[12], line 4
1 students = dict([(123451, 'Huber'), (123451, 'Langer'), (213131, 'Schmidt'), (4131129, 'Langer')])
3 values = students.values()
----> 4 values[0] = 'Test'
TypeError: 'dict_values' object does not support item assignment
Sie werden als sog. Ansichten (engl. View Objects) bezeichnet.
Das bedeutet kurz gesagt: Änderungen am Wörterbuch werden in diesen Datenstrukturen übernommen, doch können wir Ansichten nicht direkt ändern.
students.values()
gibt uns eine Ansicht auf die Werte des Wörterbuchs students
.
students = dict([(123451, 'Huber'), (123451, 'Langer'), (213131, 'Schmidt'), (4131129, 'Langer')])
values = students.values()
print(values)
students[123451] = 'Müller'
print(values)
dict_values(['Langer', 'Schmidt', 'Langer'])
dict_values(['Müller', 'Schmidt', 'Langer'])
In diesem Beispiel ist die letzte Zeile interessant.
Obwohl wir values
nicht verändern, wird es durch unsere Änderungen am Wörterbuch students
verändert.
Dies ist ein sog. erwünschter Seiteneffekt.
14.9.5. Wörterbücher und der Speicher#
Wie Wörterbücher im Speicher realisiert werden erläutern wir ansatzweise im Abschnitt Mengen und tiefgreifender im Kapitel Namensregister im Abschnitt Hashing und das Dictionary.