Dictionaries

Einführung

In Python kennt man noch Datentypen der Kategorie "Mapping", was im Prinzip nur dem Dictionary entspricht. Ein Dictionary ist ein assoziatives Feld. Assoziative Felder werden in Perl übrigens als Hashes bezeichnet. Ein Dictionary besteht aus Schlüssel-Objekt-Paaren. Zu einem bestimmten Schlüssel gehört immer ein Objekt. Man kann also die Schlüssel auf die Objekte "abbilden", daher der Kategorienname Mapping.

In diesem Kapitel geht es aber nicht nur um Dictionaries sondern am Ende beschäftigen wir uns auch noch mit dem Zusammenhang zwischen Listen und Dictionaries, d.h. wir zeigen wie man aus Dictionaries Listen erzeugt und umgekehrt, wie man aus bestimmten Listen Dictionaries erzeugen kann.

Zunächst wollen wir jedoch ein Beispiel für ein Dictionary vorstellen:
>>> woerter = {"house" : "Haus", "cat":"Katze", "black":"schwarz"}
>>> woerter["house"]
'Haus'
>>> woerter["cat"]
'Katze'
In einem Dictionary können beliebige Typen als Werte verwendet werden. Bei den Schlüsseln gilt jedoch die Einschränkung, dass nur Instanzen unveränderlicher (immutable) Datentypen verwendet werden können, also z.B. keine Listen und keine Dictionaries.
Ansonsten erhält man eine Fehlermeldung:
>>> dic = { [1,2,3]:"abc"}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list objects are unhashable
Aber Tupel als Schlüssel sind okay, wie man im folgenden Beispiel sieht:
>>> dic = { (1,2,3):"abc", 3.1415:"abc"}
>>> dic
{3.1415: 'abc', (1, 2, 3): 'abc'}

Operatoren auf Dictionaries

Operator
Erklärung
len(d)
liefert die Anzahl aller im Dictionary enthaltenen Elemente, d.h. Schlüssel-Werte-Paare
del d[k]
Löschen des Schlüssels k zusammen mit seinem Wert
k in d
True, wenn es im Dictionary  d einen Schlüssel k gibt
k not in d
True, wenn es im Dictionary d keinen Schlüssel k gibt

Zugriff auf nicht existierende Schlüssel

Versucht man auf nicht existierende Schlüssel zuzugreifen, erhält man eine Fehlermeldung:

>>> woerter = {"house" : "Haus", "cat":"Katze"}
>>> woerter["car"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'car'
Man kann dies wie folgt absichern:
>>> if "car" in woerter: print woerter["car"]
... 
>>> if "cat" in woerter: print woerter["cat"]
... 
Katze

Wichtige Methoden

Mit der Methode copy() kann man ein Dictionary kopieren:
>>> w = woerter.copy()
>>> woerter["cat"]="chat"
>>> print w
{'house': 'Haus', 'cat': 'Katze'}
>>> print woerter
{'house': 'Haus', 'cat': 'chat'}
Mit clear() löscht man den Inhalt eines Dictionary löschen. Das Dictionary an sich bleibt aber bestehen:
>>> w.clear()
>>> print w
{}

Update: Einhängen eines weiteren Dictionary

Mit der Methode update kann man ein zweites Dictionary in ein Dictionary einhängen. Enthält das zweite Dictionary Schlüssel, die auch im ersten vorkommen, so werden diese mit den Werten des zweiten überschrieben.

>>> w={"house":"Haus","cat":"Katze","red":"rot"}
>>> w1 = {"red":"rouge","blau":"bleu"}
>>> w.update(w1)
>>> print w
{'house': 'Haus', 'blau': 'bleu', 'red': 'rouge', 'cat': 'Katze'}

Iteration über ein Dictionary

Es bedarf keiner Methode, um über die Schlüssel eines Dictionarys zu iterieren:

for key in d:
	print key
Man kann aber auch die Methode iterkeys() benutzen, die einem speziell die Schlüssel liefert:
for key in d.iterkeys():
	print key
Mit der Methode itervalues() iteriert man direkt über die Werte:
for val in d.itervalues():
	print val
Was natürlich äquivalent zu der folgenden Schleife ist:
for key in d:
	print d[key]


Zusammenhang zwischen Listen und Dictionaries

Reißverschluss auf Kugel in Anspielung auf die Python-Funktion zip. Wenn man eine Weile mit Listen und Dictionaries unter Python gearbeitet hat, kommt nahezu zwangsläufig der Punkt, dass man Listen in Dictionaries oder umgekehrt Dictionaries in Listen wandeln will bzw. muss. Es wäre nicht allzu schwer, direkt mit den bisher bekannten Funktionen sich neue Funktionen zu schreiben, die genau dies bewerkstellen. Aber Python wäre nicht Python, wenn es hierfür nicht auch Hilfen zur Verfügung stellen würde.

Es bietet sich an, ein Dictionary der Art

{"list":"Liste", "dictionary":"Wörterbuch", "function":"Funktion"}

als Liste von 2-Tupel darzustellen.

[("list","Liste"), ("dictionary","Wörterbuch"), ("function","Funktion")]

Dictionaries in Listen

Mit den Methoden items(), keys() und values() kann man aus Dictionaries Listen erzeugen. Also z.B. mittels keys() eine Liste, die nur aus den Schlüsseln des Dictionary besteht oder mit values() eine Liste, die nur aus den Werten ohne die Schlüssel besteht. Mit items() erzeugt man eine Liste mit Wertepaaren. Das folgende Beispiel zeigt dies:

>>> w={"house":"Haus","cat":"Katze","red":"rot"}
>>> w.items()
[('house', 'Haus'), ('red', 'rot'), ('cat', 'Katze')]
>>> w.keys()
['house', 'red', 'cat']
>>> w.values()
['Haus', 'rot', 'Katze']
Semantisch gesehen beinhaltet eine Liste, die mittels der Methode items() aus einem Dictionary erzeugt wurde, den kompletten Informationsgehalt des ursprünglichen Dictionary. Allerdings gibt es keine Zugriffsfunktionen über die Schlüssel (Keys), d.h. die erste Komponente der 2-Tupel) und der Werte (Values), also der zweiten KOmponente der 2-Tupel.

Listen on Dictionares

Auch wenn wir uns im folgenden ein wenig mit Essen beschäftigen bleibt dies ein Python-Kurs und wird kein Kochkurs.
Nehmen wir an, dass wir zwei Listen haben, von denen eine die Keys und die andere die Werte enthält:
>>> gerichte = ["Pizza", "Sauerkraut", "Paella", "Hamburger"]
>>> laender = ["Italien","Deutschland","Spanien","USA"]
Nun wollen wir ein Dictionary erzeugen, dass einem Gericht ein Land zuordnet. (Sorry, dass wir hier die Vorurteile bedienen.) Dazu benötigen wir die Funktion zip(). Der Name zip wurde gewählt, weil zip Reißverschluss im Englischen bedeutet. Wie ein Reißverschluss nimmt zip zwei Listen als Argumente und kombiniert sie zu einer neuen Liste zusammen. In kulinarischen Beispiel sieht das wie folgt aus:
>>> land_gericht = zip(laender,gerichte)
>>> print land_gericht
[('Italien', 'Pizza'), ('Deutschland', 'Sauerkraut'), ('Spanien', 'Paella'), ('USA', 'Hamburger')]
>>> 
In der Variablen land_gericht haben wir nun ein "Dictionary" in der 2-Tupel-Form. Was wir aber eigentlich wollen ist ein richtiges Python-Dictionary. Glücklicherweise gibt es auch hierfür eine Funktion. dict() nimmt als Argument eine Liste der obigen Form und wandelt sie in ein Dictionary um:
>>> land_gericht_dict = dict(land_gericht)
>>> print land_gericht_dict
{'Spanien': 'Paella', 'Italien': 'Pizza', 'Deutschland': 'Sauerkraut', 'USA': 'Hamburger'}
>>> 
Ein Frage stellt sich noch bezüglich der Funktion zip(). Was passiert, wenn eine der beiden Listen mehr Elemente als die andere hat? Ganz einfach, die überzähligen Elemente werden nicht verarbeitet, d.h. sie kommen nicht in die Ergebnisliste.
>>> laender = ["Italien","Deutschland","Spanien","USA","Schweiz"]
>>> gerichte = ["Pizza", "Sauerkraut", "Paella", "Hamburger"]
>>> land_gericht = zip(laender,gerichte)
>>> print land_gericht
[('Italien', 'Pizza'), ('Deutschland', 'Sauerkraut'), ('Spanien', 'Paella'), ('USA', 'Hamburger')]
>>> 
Die brennende Frage, was wohl das Nationalgericht der Schweiz ist, bleibt, zumindest was diesen Kurs betrifft unbeantwortet!