Dictionaries


Einführung

Webster's Dictionary In den vorigen Kapiteln haben wir die sequentiellen Datentypen wie Listen, Strings und Tupel eingeführt. Nun wollen wir eine weitere Kategorie von Datentypen genauer untersuchen, die "Mapping". In dieser Kategorie gibt es allerdings zur Zeit nur einen implementierten Typ, das Dictionary. Beim Dictionary handelt es sich um ein assoziatives Feld. Assoziative Felder werden in verschiedenen Programmiersprachen mit verschiedenen Namen versehen. So spricht man in Java und C++ von einer Map, in Perl und Ruby von einem Hash und wie in Python bezeichnen auch Smalltalk, Objective-C und C# assoziative Arrays als Dictionaries.

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.

Dictionaries gehören zu den wichtigsten Datentypen von Python. Kaum ein Programm oder Skript kommt ohne Dictionaries aus. Wie Listen können Dictionaries leicht verändert werden, außerdem können sie beliebig wachsen und schrumpfen während der Laufzeit.

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.


Beispiele für Dictionaries

Wir beginnen mit dem wohl einfachsten Fall eines Dictionary, ein leeres Dictionary:

>>> empty = {}
>>> empty
{}
Zu Ehren des Schutzheiligen von Python "Monty Python" definieren wir nun ein spezielles kulinarisches Dictionary. Was wäre Python und auch das Internet ohne "ham", "egg" und "spam"?
>>> food = {"ham" : "yes", "egg" : "yes", "spam" : "no" }
>>> food
{'egg': 'yes', 'ham': 'yes', 'spam': 'no'}
>>> food["spam"] = "yes"
>>> food
{'egg': 'yes', 'ham': 'yes', 'spam': 'yes'}
>>> 
Im nächsten Beispiel kreieren wir ein einfaches Deutsch-Englisches Wörterbuch als Dictionary:
>>> en_de = {"red" : "rot", "green" : "grün", "blue" : "blau", "yellow":"gelb"}
>>> print(en_de)
{'blue': 'blau', 'green': 'grün', 'yellow': 'gelb', 'red': 'rot'}
>>> 
Wie wäre es mit einem weiteren Dictionary, eines was von Deutsch nach Französisch übersetzt? Damit sind wir dann aber auch in der Lage von Englisch nach Französisch zu übersetzen, indem wir die beiden Dictionaries hintereinander schalten, wie wir im folgenden Beispiel demonstrieren. Mit Hilfe dieses Dictionarys können wir nun von Englisch nach Französisch übersetzen, obwohl wir gar kein Englisch-Französisch-Wörterbuch haben. So gibt uns de_fr[en_de["red"]] das französische Wort für "red", also "rouge". Dies geschieht in zwei Schritten: Erst wird von Python der Ausdruck en_de["red"] ausgewertet. Das Ergebnis der Auswertung "rot" wird dann im de_fr-Dictionary "nachgeschaut", d.h. de_fr["rot"] liefert nun "rouge" zurück:

>>> en_de = {"red" : "rot", "green" : "grün", "blue" : "blau", "yellow":"gelb"}
>>> print(en_de)
{'blue': 'blau', 'green': 'grün', 'yellow': 'gelb', 'red': 'rot'}
>>> print(en_de["red"])
rot
>>> de_fr = {"rot" : "rouge", "grün" : "vert", "blau" : "bleu", "gelb":"jaune"}
>>> print("The French word for red is: " + de_fr[en_de["red"]])
The French word for red is: rouge
>>> 

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: unhashable type: 'list'
Tupel als Schlüssel sind in Ordnung, wie wir im folgenden Beispiel sehen:
>>> dic = { (1,2,3):"abc", 3.1415:"abc"}
>>> dic
{3.1415: 'abc', (1, 2, 3): 'abc'}

Nun wollen wir unsere Beispiele mit Wörterbüchern für natürliche Sprachen noch ein wenig aufpeppen. Dazu definieren wir eine Dictionary von Dictionaries:
>>> en_de = {"red" : "rot", "green" : "grün", "blue" : "blau", "yellow":"gelb"}
>>> de_fr = {"rot" : "rouge", "grün" : "vert", "blau" : "bleu", "gelb":"jaune"}
>>> 
>>> dictionaries = {"en_de" : en_de, "de_fr" : de_fr }
>>> 
>>> print(dictionaries["de_fr"]["blau"])
bleu
>>> 


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


Beispiele:
Das folgende Dictionary enthält den Morsecode.
morse = {
"A" : ".-", 
"B" : "-...", 
"C" : "-.-.", 
"D" : "-..", 
"E" : ".", 
"F" : "..-.", 
"G" : "--.", 
"H" : "....", 
"I" : "..", 
"J" : ".---", 
"K" : "-.-", 
"L" : ".-..", 
"M" : "--", 
"N" : "-.", 
"O" : "---", 
"P" : ".--.", 
"Q" : "--.-", 
"R" : ".-.", 
"S" : "...", 
"T" : "-", 
"U" : "..-", 
"V" : "...-", 
"W" : ".--", 
"X" : "-..-", 
"Y" : "-.--", 
"Z" : "--..", 
"0" : "-----", 
"1" : ".----", 
"2" : "..---", 
"3" : "...--", 
"4" : "....-", 
"5" : ".....", 
"6" : "-....", 
"7" : "--...", 
"8" : "---..", 
"9" : "----.", 
"." : ".-.-.-", 
"," : "--..--"
}
Sie können obiges Dictionary als morsecode.py abspeichern, um die folgenden Beispiele leichter nachvollziehen zu können. Zuerst müssen wir das Dictionary wie folgt importieren:
from morsecode import morse
Die Anzahl der verschiedenen Zeichen für die unser Dictionary eine Abbildung in ein Morsezeichen besitzt, können wir mittels len() bestimmen:
>>> len(morse)
38
Unser Dictionary enthält nur Großbuchstaben. "a" in morse liefert deshalb zum Beispiel False zurück:
>>> "a" in morse
False
>>> "A" in morse
True
>>> "a" not in morse
True


pop() und popitem()

pop

Listen können als Stack gesehen und benutzt werden. Dabei wird die pop()-Methode benutzt um ein Element vom Stack zu nehmen. So weit so gut, wenn es um Listen geht, aber macht die pop()-Methode Sinn für Dictionaries. Schließlich ist der dict-Typ kein sequentieller Datentyp, hat also keine Anordnung und keine Indizierung. Aber es gibt dennoch eine pop-Methode für Instanzen des Typs dict. Allerdings ist pop() anders definiert.
Falls D ein Dictionary bezeichnet, dann entfernt D.pop(k) den Index k zusammen mit seinem Wert aus dem Dictionary, außerdem liefert D.pop(k) den Wert von D[k] als Rückgabewert zurück.
Falls der Schlüssel nicht in D gefunden wird, wird der KeyError generiert:
>>> capitals = {"Österreich":"Wien", "Deutschland":"Berlin", "Niederlande":"Amsterdam"}
>>> capital = capitals.pop("Deutschland")
>>> print(capital)
Berlin
>>> print(capitals)
{'Niederlande': 'Amsterdam', 'Österreich': 'Wien'}
>>> capital = capitals.pop("Schweiz")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'Schweiz'
>>> 
Der Versuch die Hauptstadt der Schweiz zu ermitteln führte im vorigen Beispiel zum Ausnahmefehler KeyError, weil es diesen Eintrag im Dictionary nicht gibt. Um solche Fehler zu vermeiden, gibt es einen eleganten Weg in Python. Die Methode pop() hat dazu einen zweiten optionalen Parameter, mit dem man einen Default-Wert für diesen Fall mitgeben kann:
>>> capital = capitals.pop("Schweiz","unbekannt")
>>> print(capital)
unbekannt
>>> capitals.pop("Niederlande","unbekannt")
'Amsterdam'
>>> capitals.pop("Niederlande","unbekannt")
'unbekannt'
>>> 

popitem

popitem() ist eine Methode von dict, die keine Parameter benötigt und die beliebiges (Schlüssel,Wert)-Paar als Zweiertupel zurückliefert. Wendet man popitem() auf ein leeres Dictionary an, wird der Ausnahmefehler KeyError generiert:
>>> capitals = {"Hessen":"Wiesbaden", "Saarland":"Saarbrücken", "Baden-Württemberg":"Stuttgart", "Rheinland-Pfalz":"Mainz", "Nordrhein-Westfalen":"Düsseldorf"}
>>> (land, capital) = capitals.popitem()
>>> print(land, capital)
Hessen Wiesbaden
>>> pair = capitals.popitem()
>>> print(pair)
('Nordrhein-Westfalen', 'Düsseldorf')
>>> print(capitals)
{'Saarland': 'Saarbrücken', 'Baden-Württemberg': 'Stuttgart', 'Rheinland-Pfalz': 'Mainz'}
>>> 


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

Eine weitere Methode auf die Werte über die Schlüssel zuzugreifen ist mit der Methode get() gegeben. Auch ihr kann als zweiter Parameter ein Default-Wert mitgegeben werden:
>>> capitals = {"Sachsen":"Dresden", "Niedersachsen":"Hannover", "Brandenburg":"Potsdam"}
>>> capital = capitals["Sachsen"]
>>> print(capital)
Dresden
>>> capital = capitals["Thüringen"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'Thüringen'
>>> capital = capitals.get("Sachsen")
>>> print(capital)
Dresden
>>> capital = capitals.get("Thüringen")
>>> print(capital)
None
>>> capital = capitals.get("Thüringen","Erfurt")
>>> print(capital)
Erfurt
>>> 


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'}
Bei diesem Kopieren handelt es sich um eine flache (shallow) Kopie. Wenn es sich bei einem Wert um einen komplexen Datentyp, wie z.B. eine Liste oder ein anderes Dictionary handelt, wirken sich Änderungen innerhalb eines solchen Wertes sowohl auf die Kopie als auch auf das Original aus:
# -*- coding: utf-8 -*-

trainings = { "course1":{"title":"Python Training Course for Beginners", 
                         "location":"Frankfurt", 
                         "trainer":"Steve G. Snake"},
              "course2":{"title":"Intermediate Python Training",
                         "location":"Berlin",
                         "trainer":"Ella M. Charming"},
              "course3":{"title":"Python Text Processing Course",
                         "location":"München",
                         "trainer":"Monica A. Snowdon"}
              }

trainings2 = trainings.copy()

trainings["course2"]["title"] = "Perl Training Course for Beginners"
print(trainings2)
Wenn wir uns die Ausgaben anschauen, sehen wir, dass der "title" von "course2" sowohl in trainings und trainings2 sich geändert hat:
{'course2': {'trainer': 'Ella M. Charming', 'name': 'Perl Training Course for Beginners', 'location': 'Berlin'}, 'course3': {'trainer': 'Monica A. Snowdon', 'name': 'Python Text Processing Course', 'location': 'München'}, 'course1': {'trainer': 'Steve G. Snake', 'name': 'Python Training Course for Beginners', 'location': 'Frankfurt'}}
Alles funktioniert so, wie man sich eine Kopie vorstellt, wenn man einem Schlüssel einen komplett neuen Wert, also ein neues Objekt zuordnet:
trainings = { "course1":{"title":"Python Training Course for Beginners", 
                         "location":"Frankfurt", 
                         "trainer":"Steve G. Snake"},
              "course2":{"title":"Intermediate Python Training",
                         "location":"Berlin",
                         "trainer":"Ella M. Charming"},
              "course3":{"title":"Python Text Processing Course",
                         "location":"München",
                         "trainer":"Monica A. Snowdon"}
              }

trainings2 = trainings.copy()

trainings["course2"] = {"title":"Perl Seminar for Beginners",
                         "location":"Ulm",
                         "trainer":"James D. Morgan"}
print(trainings2["course2"])
Die Ausgabe sieht wie folgt aus:
{'trainer': 'Ella M. Charming', 'location': 'Berlin', 'title': 'Intermediate Python Training'}


Für diejenigen, die mehr über die tieferen Gründe für dieses Verhalten erfahren wollen, empfehlen wir unser Kapitel über "Flaches und tiefes Kopieren".

Der Inhalt eines Dictionary kann mittels der Methode clear() geleert werden. Das Dictionary wird dabei nicht gelöscht sondern wirklich nur geleert:
>>> trainings.clear()
>>> print(trainings)
{}


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:

>>> d = {"a":123, "b":34, "c":304, "d":99}
>>> for key in d:
...     print(key)
... 
b
c
a
d
>>> 
Man kann aber auch die Methode keys() benutzen, die einem speziell die Schlüssel liefert:
>>> for key in d.keys():
...     print(key)
... 
b
c
a
d
>>> 
Mit der Methode values() iteriert man direkt über die Werte:
>>> for value in d.values():
...     print(value)
... 
34
304
123
99
>>> 
Wenn man nur auf die Ergebnisse schaut, ist das äquivalent zu der folgenden Schleife:
for key in d:
	print(d[key])
Was die Implementierung und die Effizienz betrifft, ist die letzte Methode jedoch weniger effizient.
Im Folgenden zeigen wir, dass der erste Weg deutlich schneller ist. Um das Folgende zu verstehen, sollte man sich mit %%timeit von ipython auskennen:
In [5]: %%timeit  d = {"a":123, "b":34, "c":304, "d":99}
for key in d.keys():
    x=d[key]
   ...: 
1000000 loops, best of 3: 225 ns per loop

In [6]: %%timeit  d = {"a":123, "b":34, "c":304, "d":99}
for value in d.values():
    x=value
   ...: 
10000000 loops, best of 3: 164 ns per loop

In [7]: 


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")]


Listen oder Mengen aus Dictionaries generieren

Immer wieder kommt es vor, dass man ein Dictionary hat und man aus diesem Dictionary Mengen oder Listen erzeugen will.
Betrachten wir dazu das folgende Dictionary mit englisch-deutschen Farben:

>>> colours = {"red":"rot", "green":"grün", "blue":"blau", "yellow":"gelb"}

Nehmen wir nun an, dass wir daraus gerne die Menge aller Schlüssel, also alle englischen Farbadjektive extrahieren wollen. Dazu bietet die Klasse dict die Methode "keys" an.
Zu dieser Methode sagt uns die help-Funktion help(dict.keys):
Help on method_descriptor:

keys(...)
    D.keys() -> a set-like object providing a view on D's keys
(END)
Zu Deutsch bedeutet dies, dass D.Keys für ein Dictionary D ein Mengen-ähnliches Objekt zurückliefert, was uns eine "view" (Sicht) auf die Schlüssel (keys) von D liefert. Eine "view" ist ein spezielles Python-Objekt, was in diesem Fall, wie die Hilfe sagt, ein einer Menge ähnelndes Objekt erzeugt. Dieses Objekt ist aber ein Iterator, der seine Elemente aus dem Dictionary generiert, ohne dass eine Menge generiert wird. Es erfolgt also keine Kopie.
>>> english_colours = colours.keys()
>>> english_colours
dict_keys(['green', 'blue', 'yellow', 'red'])
Im folgenden Beispiel können wir sehen, dass sich diese View auch "ändert", wenn das Dictionary geändert wurde:
>>> colours["black"] = "schwarz"
>>> english_colours
dict_keys(['yellow', 'black', 'blue', 'red', 'green'])
>>> 
Möchte man aus dem dict_keys-Objekt eine "echte" Menge oder eine Liste erzeugen, so kann man dies mit den globalen Funktionen set und list bewerkstelligen:
>>> english_colours_set = set(english_colours)
>>> colours["white"] = "weiß"
>>> english_colours
dict_keys(['white', 'red', 'blue', 'green', 'yellow', 'black'])
>>> english_colours_set
{'green', 'yellow', 'black', 'blue', 'red'}
>>> english_colours_list = list(english_colours)
>>> english_colours_list
['white', 'red', 'blue', 'green', 'yellow', 'black']
>>> 
Analog dazu kann man sich auch eine view für die Werte eines Dictionaries (dict_values) mittels der Methode values erzeugen:
>>> german_colours = colours.values()
>>> german_colours
dict_values(['weiß', 'rot', 'blau', 'grün', 'gelb', 'schwarz'])
>>> 
Außerdem gibt es noch die methode items(), mit der man sich eine View der Schlüssel-Werte-Paare erzeugen kann:
>>> pairs = colours.items()
>>> pairs
dict_items([('white', 'weiß'), ('red', 'rot'), ('blue', 'blau'), ('green', 'grün'), ('yellow', 'gelb'), ('black', 'schwarz')])
>>> set(pairs)
{('red', 'rot'), ('green', 'grün'), ('yellow', 'gelb'), ('white', 'weiß'), ('black', 'schwarz'), ('blue', 'blau')}
>>> list(pairs)
[('white', 'weiß'), ('red', 'rot'), ('blue', 'blau'), ('green', 'grün'), ('yellow', 'gelb'), ('black', 'schwarz')]
>>> 
Semantisch gesehen beinhaltet eine Liste/View, 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 in Dictionaries wandeln

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. Eigentlich kann zip noch viel mehr, aber darauf wollen wir hier nicht eingehen. In kulinarischen Beispiel sieht das wie folgt aus:
>>> land_gericht = list(zip(laender,gerichte))
>>> print(land_gericht)
[('Italien', 'Pizza'), ('Deutschland', 'Sauerkraut'), ('Spanien', 'Paella'), ('USA', 'Hamburger')]
>>> 
In der Variablen land_gericht haben wir nun Liste, in der die Elemete 2-Tupel sind mit den Schlüssel und den Werten. Logisch gesehen sind wir also einem Dictionary schon sehr nahe. 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!

Alles in einem Schritt

Normalerweise empfehlen wir nicht zu viele Schritte in eine Anweisung oder einen Ausdruck zu stecken, auch wenn dies eindrucksvoll ausschauen mag und der Code dadurch sehr klein und kompakt wird. Es ist häufig besser Zwischenschritte mit sprechenden Variablen einzubauen. Dadurch wird die Lesbarkeit und Verständlichkeit eines Programmes erhöht.
Unser vorheriges kulinarisches Dictionary könnten wir in einem Schritt schreiben:
>>> country_specialities_dict = dict(list(zip(["pizza", "sauerkraut", "paella", "hamburger"], ["Italy", "Germany", "Spain", "USA"," Switzerland"])))
>>> print(country_specialities_dict)
{'paella': 'Spain', 'hamburger': 'USA', 'sauerkraut': 'Germany', 'pizza': 'Italy'}
>>> 
Andererseits sind die Zwischenschritte im folgenden Code möglicherweise des Guten zu viel:
>>> dishes = ["pizza", "sauerkraut", "paella", "hamburger"]
>>> countries = ["Italy", "Germany", "Spain", "USA"]
>>> country_specialities_zip = zip(dishes,countries)
>>> country_specialities_list = list(country_specialities_zip)
>>> country_specialities_dict = dict(country_specialities_list)
>>> print(country_specialities_dict)
{'sauerkraut': 'Germany', 'paella': 'Spain', 'hamburger': 'USA', 'pizza': 'Italy'}
>>> 
Wir erhalten das gleiche Ergebnis, wie im Einzeiler.

Lauernde Gefahr

Insbesondere für diejenigen, die von Python 2.x auf Python 3.x wechseln lauert im obigen Vorgehen eine große Gefahr: zip() lieferte in Python2 eine Liste zurück. In Python 3.x hingegen liefert zip nun einen Iterator zurück. Man sollte sich immer vergegenwärtigen, dass sich viele Iteratoren bei der Benutzung "verbrauchen", das bedeutet, dass man sie nur einmal durchlaufen kann.

Wir demonstrieren dies im Folgenden kleinen Beispiel:
>>> l1 = ["a","b","c"]
>>> l2 = [1,2,3]
>>> c = zip(l1, l2)
>>> for i in c:
...     print(i)
... 
('a', 1)
('b', 2)
('c', 3)
>>> for i in c:
...     print(i)
... 
Diesen Effekt kann man auch beobachten, wenn man list() benutzt:
>>> l1 = ["a","b","c"]
>>> l2 = [1,2,3]
>>> c = zip(l1,l2)
>>> z1 = list(c)
>>> z2 = list(c)
>>> print(z1)
[('a', 1), ('b', 2), ('c', 3)]
>>> print(z2)
[]
Als Übung können Sie überlegen, was im folgenden Skript faul ist:
dishes = ["pizza", "sauerkraut", "paella", "hamburger"]
countries = ["Italy", "Germany", "Spain", "USA"]
country_specialities_zip = zip(dishes,countries)
print(list(country_specialities_zip))
country_specialities_list = list(country_specialities_zip)
country_specialities_dict = dict(country_specialities_list)
print(country_specialities_dict)
startet man das Skript, sieht man, dass das Dictionary, was wir erzeugen wollen, leer ist:
$ python3 tricky_code.py 
[('pizza', 'Italy'), ('sauerkraut', 'Germany'), ('paella', 'Spain'), ('hamburger', 'USA')]
{}
$

Überspringen der zwischengeschalteten Liste

Wir wollten zeigen, dass es eine eins-zu-eins Relation zwischen der Liste mit 2-Tupeln und dem Dictionary gibt, weswegen wir die Liste erzeugt hatten. Dies ist nicht notwendig. Man kann das kulinarische Dictionary auch direkt aus dem Iterator erzeugen:
>>> dishes = ["pizza", "sauerkraut", "paella", "hamburger"]
>>> countries = ["Italy", "Germany", "Spain", "USA"]
>>> country_specialities_zip = zip(dishes,countries)
>>> country_specialities_dict = dict(country_specialities_zip)
>>> print(country_specialities_dict)
{'paella': 'Spain', 'hamburger': 'USA', 'sauerkraut': 'Germany', 'pizza': 'Italy'}
>>>