Dictionary

Allgemeines

Ein Dictionary ist ebenfalls ein zusammengesetzter Datentyp, in diesem Fall aus Schlüssel-Wert-Paaren (Key-Value-Pairs) . In anderen Programmiersprachen spricht man auch von einem Hash-Map. Gelegentlich wird auch von Assoziativspeicher oder Assoziativ-Array gesprochen, um auszudrücken, dass die Reihenfolge - im Gegensatz zu Sequenzen und Listen - keine Rolle spielt.

Im Gegensatz also zu Sequenzen und Listen, die durch Zahlen indiziert werden, werden Dictionaries durch Schlüssel indiziert. Schlüssel können alle möglichen unveränderlichen (immutable) Typen sein - in der Regel sind es Zeichenketten oder Zahlen. Tupel können ebenfalls als Schlüssel verwendet werden, vorausgesetzt sie enthalten nur Zeichenketten, Zahlen oder weitere Tupel. Falls ein Tupel ein veränderliches Objekt enthält, kann es nicht mehr als Schlüssel verwendet werden, d.h. insbesondere können deswegen keine Listen als Schlüssel verwendet werden, die ja jederzeit verändert werden können.

Eindeutigkeit der Schlüssel (unique keys)

Dictionaries sind daher eine ungeordnete und auch in einer beliebigen Reihenfolge abgespeicherte Menge von Schlüssel:Wert Paaren (key: value pairs) mit der zusätzlichen Bedingung, dass die Schlüssel in einem Dictionary eindeutig (unique) sind.

Syntax

Geschweifte Klammern

Ein Paar von geschweiften Klammern erzeugt ein leeres Dictionary:

In [2]:
a = {}
print(a)
{}

Eine Liste von komma-getrennten (comma-separated) Schlüssel:Wert Paaren in diesen geschweiften Klammern fügt erste Schlüssel-Wert-Paare diesem Dictionary hinzu. Dictionaries werden auch auf diese Weise ausgegeben.

In [3]:
kernobst = {'Birnen':2,'Äpfel':8,'Quitten':6}
print(kernobst)
{'Birnen': 2, 'Äpfel': 8, 'Quitten': 6}

Funktion dict()

Die Funktion dict() erzeugt ebenfalls Dictionaries. Dies kann sowohl über eine Sequenz von Schlüssel-Wert-Paaren als auch über Schlüsselwert-Argumente - vorausgesetzt die Schlüssel sind Zeichenketten - geschehen.

In [4]:
südfrüchte = dict([('Ananas', 2), ('Bananen', 6), ('Orange', 4)])
print(südfrüchte)
{'Ananas': 2, 'Bananen': 6, 'Orange': 4}
In [5]:
steinobst = dict(Aprikosen=3, Kirschen=12, Pflaumen=9)
print(steinobst)
{'Aprikosen': 3, 'Kirschen': 12, 'Pflaumen': 9}

Dictionary Comprehension

Analog wie die List Comprehension kann auch ein Dictionary über eine Dictionary Comprehension aus beliebigen Ausdrücken mit Schlüsseln und Werten erstellt werden.

In [6]:
quadr = {x: x**2 for x in (2, 4, 6)}
print(quadr)
{2: 4, 4: 16, 6: 36}

Zugriff über den Schlüssel

Die Hauptanwendung eines Dictionaries ist das Abspeichern eines Wertes mit seinem Schlüssel sowie das anschliessende Herausholen dieses Wertes mit dem entsprechenden Schlüssel. Die einzelnen Komponenten eines Dictionary werden also über den Schlüssel angesprochen und nicht über den Index. Wenn ein Wert einem bereits vorhandenen Schlüssel zugewiesen wird, dann wird der vorher vorhandene Wert - analog wie bei einer Variablen - überschrieben.

In [7]:
kernobst['Birnen'] = 4
print(kernobst)
{'Birnen': 4, 'Äpfel': 8, 'Quitten': 6}

Einen nicht vorhandenen Schlüssel in einem Dictionary aufzurufen ergibt einen Fehler, daher sollte mit dem in-Operator vorher abgefragt werden, ob ein Schlüssel in einem Dictionary vorhanden ist. Allerdings kann ein neues Schlüssel-Wert-Paar über eine Zuweisung neu erstellt werden.

In [8]:
print(kernobst['Pflaumen'])
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-8-89c08c687b19> in <module>()
----> 1 print(kernobst['Pflaumen'])

KeyError: 'Pflaumen'
In [9]:
print('Pflaumen' in kernobst)
False
In [10]:
steinobst['Pfirsich'] = 2
print(steinobst)
{'Aprikosen': 3, 'Kirschen': 12, 'Pflaumen': 9, 'Pfirsich': 2}
In [11]:
print('Pflaumen' in steinobst)
True

Dictionary-Methoden

Hier finden sie eine Aufzählung der wichtigsten Dictionary-Methoden. In dieser Auflistung ist wieder dict der Methode als Platzhalter für ein Dictionary vorangestellt. In den weiteren Literaturhinweisen ist die komplette Aufzählung aller Dictionary-Methoden zu finden.

  • dict.keys()

    Gibt eine neue Sicht von allen in dem Dictionary dict benutzten Schlüsseln zurück. Insbesondere wird mit list(dict.keys()) eine Liste zurückgegeben.

  • dict.items()

    Gibt eine neue Sicht aller Komponenten des Dictionaries als Schlüssel-Wert-Paare zurück.

  • dict.values()

    Gibt eine neue Sicht von allen in dem Dictionary vorhandenen Werten zurück.

  • dict.get(key[, default])

    Gibt den Wert für den Schlüssel key zurück, falls der Schlüssel in dem Dictionary existiert, andernfalls wird der Wert default zurückgegeben. Falls default nicht angegeben ist, ist der Wert von default None, sodass diese Methode niemals einen KeyError wirft.

  • dict.setdefault(key[, default])

    Gibt den Wert für den Schlüssel key zurück, falls der Schlüssel in dem Dictionary existiert, andernfalls wird das Schlüssel-Wert-Paas key:default an das Dictionary angehängt und der Wert default zurückgegeben. Falls default nicht angegeben ist, ist der Wert von default None.

  • dict.update([other])

    Aktualisiert das Dictionary mit den Schlüssel-Wert-Paaren aus dem Objekt other und überschreibt bereits existierende Schlüssel mit den Werten aus dem Objekt other und gibt None als Ergebnis zurück.

    Das Objekt other kann dabei sowohl ein anderes Dictionary sein als auch ein iterierbares Objekt von Schlüssel-Wert-Paaren entweder als Tupel oder anderen iterierbaren Objekten der Länge 2 (d.h. Schlüssel und Wert). Es können auch Schlüsselwort-Argumente in update übergeben werden, dann wird das Dictionary mit diesen Schlüssel-Wert-Paaren aktualisiert (z.B. dict.update(red=1, blue=2)).

In [12]:
print(südfrüchte)
zitronen = südfrüchte.setdefault('Zitronen',5)
print(zitronen)
print(südfrüchte)
{'Ananas': 2, 'Bananen': 6, 'Orange': 4}
5
{'Ananas': 2, 'Bananen': 6, 'Orange': 4, 'Zitronen': 5}
In [13]:
obst = steinobst
obst.update(kernobst)
print(obst)
{'Aprikosen': 3, 'Kirschen': 12, 'Pflaumen': 9, 'Pfirsich': 2, 'Birnen': 4, 'Äpfel': 8, 'Quitten': 6}
In [14]:
%%Mooc StringAssessment
Out[14]:

Dictionary

Es ist folgender Code gegeben:


südfrüchte = {'Orange': 4, 'Ananas': 2, 'Bananen': 6, 'Zitronen': 5}
obst = {'Äpfel': 8, 'Quitten': 6, 'Aprikosen': 3, 'Pflaumen': 9, 'Birnen': 4, 'Pfirsich': 2, 'Kirschen': 12}
obst.update(südfrüchte)

Verwenden sie zur Berechnung der Summe aller Obststücke die Builtin-Funktion sum()

Geben sie den Code zur Berechnung aller Obststücke an



Dictionary Sichten (Dictionary View Objects)

Die Objekte, die durch die Methoden dict.keys(), dict.values() und dict.items() zurückgegeben werden sind Dictionary Sichten (view objects). Sie stellen eine dynamische Sicht auf die Einträge in dem Dictionary dar. Dies bedeutet, dass bei einer Änderung des Dictionaries die Sicht ebenfalls sofort verändert.

In [15]:
obstKeys = obst.keys()
print(list(obstKeys))
['Aprikosen', 'Kirschen', 'Pflaumen', 'Pfirsich', 'Birnen', 'Äpfel', 'Quitten']

Wenn ein Schlüssel nicht existiert und trotzdem darauf zugegriffen wird, wird ein KeyError geworfen.

In [16]:
del obst['Erdbeeren']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-16-f61a0c3363fe> in <module>()
----> 1 del obst['Erdbeeren']

KeyError: 'Erdbeeren'
In [17]:
del obst['Quitten']
print(obst)
{'Aprikosen': 3, 'Kirschen': 12, 'Pflaumen': 9, 'Pfirsich': 2, 'Birnen': 4, 'Äpfel': 8}

Weitere Beispiele

Indizes einer Liste als Schlüssel

Verwenden wir die Liste der Primzahlen aus dem Kapitel Grundlagen:

In [18]:
primzahlen = [2,3,5,7,11,13,17,19,23,29]

und wollen hieraus ein Dictionary erstellen mit dem Listenindex als Schlüsselwort, dann kann dies auf verschiedenste Art und Weise durchgeführt werden

1) in einer Schleife über alle Indizes

In [19]:
primDictionary = {}
for i in range(len(primzahlen)):
    primDictionary[i] = primzahlen[i]
print(primDictionary)
{0: 2, 1: 3, 2: 5, 3: 7, 4: 11, 5: 13, 6: 17, 7: 19, 8: 23, 9: 29}

2) in einer Schleife über alle Primzahlen und der update-Methode

In [20]:
primDictionary = {}
for p in primzahlen:
    primDictionary.update({primzahlen.index(p):p})
print(primDictionary)
{0: 2, 1: 3, 2: 5, 3: 7, 4: 11, 5: 13, 6: 17, 7: 19, 8: 23, 9: 29}

3) über die Zip Funktion

In [21]:
primDictionary = dict(zip(range(10),primzahlen))
print(primDictionary)
{0: 2, 1: 3, 2: 5, 3: 7, 4: 11, 5: 13, 6: 17, 7: 19, 8: 23, 9: 29}
In [22]:
%%Mooc StringAssessment
Out[22]:

Dictionary mit Integer-Werten als Schlüssel

Es ist folgender Code gegeben:


primDictionary = {0: 2, 1: 3, 2: 5, 3: 7, 4: 11, 5: 13, 6: 17, 7: 19, 8: 23, 9: 29}

Geben sie den Ausdruck an, um die 4. Primzahl zu bekommen



In [23]:
%%Mooc StringAssessment
Out[23]:

Dictionary - Items

Es ist folgender Code gegeben:


primDictionary = {0: 2, 1: 3, 2: 5, 3: 7, 4: 11, 5: 13, 6: 17, 7: 19, 8: 23, 9: 29}
print(list(primDictionary.items())[-3])

Geben sie die Ausgabe des Print-Befehls an



Objekttyp als Schlüssel

Wenn bei einem Dictionary die Indizes aus einer Liste als Schlüssel verwendet werden (wie bei dem obigen Beispiel) wird aber der eigentliche Wert des Dictionary - nämlich die Unabhängigkeit von der Reihenfolge - nicht deutlich. Erst mit dem folgenden Beispiel, in dem auch ersichtlich wird, dass ein Dictionary unterschiedlichste Datentypen beinhalten kann, wird der eigentliche Vorteil der Schlüssel deutlich.

In [24]:
hsz = {'Organisation':'Hochschulzentrum Donau-Ries', 'Strasse':'Emil-Eigner-Straße', 'Hausnummer':1, 'Plz':86720, 'Stadt':'Nördlingen'}
In [25]:
plz = hsz['Plz']

Daher gibt es im Gegensatz zu den Listen auch keinen negativen Index oder eine Slice-Operation. Der Vorteil eines Dictionary liegt darin, dass die abgespeicherten Werte über die Schlüssel angesprochen werden und es daher egal ist, an welchem Platz das Schlüssel-Wert-Paar in dem Dictionary steht.

In [26]:
%%Mooc StringAssessment
Out[26]:

Dictionary - Unabhängigkeit von der Reihenfolge

Wenn das obige Dictionary hsz in einer anderen Variablen noe folgendermaßen abgespeichert wird:


noe = {{'Strasse':'Emil-Eigner-Straße', 'Plz':86720, 'Organisation':'Hochschulzentrum Donau-Ries', 'Hausnummer':1, 'Stadt':'Nördlingen'}}

Wie wird dann die Postleitzahl angesprochen?



Eindeutigkeit der Schlüssel

Die Frage der Eindeutigkeit der Schlüssel hängt natürlich immer vom Kontext ab. Das folgende Dictionary von Telefonnummern mit Vornamen als Schlüssel geht solange gut, bis eine weitere Person mit demselben Vornamen auftaucht.

In [27]:
telefonnr = {'Wolfgang': '0892345679', 'Hans': '015156784139', 'Erich': '082167868786', 'Edith': '080216787689'}
telefonnr['Heiner'] = '096787854127'
print(telefonnr)
{'Wolfgang': '0892345679', 'Hans': '015156784139', 'Erich': '082167868786', 'Edith': '080216787689', 'Heiner': '096787854127'}
In [28]:
%%Mooc MultipleChoiceAssessment
Out[28]:

Dictionary - eindeutiger Schlüssel

Folgende Namen stehen als Schlüssel für ein Dictionary mit Telefonnummern zur Verfügung.

Welcher Name ist davon eindeutig ?

Vorname
Nachname
Vorname Nachname
Vorname zweiterVorname Nachname
Benutzername

In [29]:
%%Mooc Video
Out[29]:

Weitere Literatur

In [30]:
%%Mooc WebReference

Dictionaries

https://docs.python.org/3/tutorial/datastructures.html#dictionaries

Hinweis: Weitere Hinweise zu Dictionaries

In [31]:
%%Mooc WebReference

Mapping Types - dict

https://docs.python.org/3/library/stdtypes.html#typesmapping

Hinweis: Auflistung aller Methoden von Dictionaries

In [32]:
%%Mooc WebReference

Dictionary View Objects

https://docs.python.org/3/library/stdtypes.html#dict-views

Hinweis: Spezielle Eigenschaften der Dictionary View Objekte