Zip Einführung

Einführung

Infektionsrate

In diesem Kapitel unseres Python-Tutorials beschäftigen wir uns mit der wunderbaren und äußerst nützlichen Funktionalität zip. Leider sind Anfänger von Python oft unnötig verwirrt und haben Angst vor der zip-Funktion. Zum einen ist der Name verwirrend, denn viele Leute verwechseln die zip-Funktion von Python mit dem bekannten Archivdateiformat ZIP, das für die verlustfreie Datenkomprimierung verwendet wird. Da diese Datenkomprimierung nicht nur den erforderlichen Speicherplatz sehr klein hält, sondern auch sehr schnell ausgeführt wird, wurde der Name 'zip' gewählt. In diesem Zusammenhang bedeutet zip "schnell handeln oder sich schnell bewegen".

Das zip von Python hat absolut nichts damit zu tun. Die Funktionalität 'zip' in Python basiert auf einer anderen Bedeutung des englischen Wortes 'zip', nämlich "etwas mit einem Reißverschluss schließen".

Wir werden sehen, dass zip sehr einfach zu verstehen sein kann. Beginnen wir mit einfachen Beispielen, bevor wir versuchen, die Theorie hinter zip zu vereinfachen.

Wir beginnen mit zwei Listen und wenden zip auf diese beiden Listen an:

buchstaben = ["a", "b", "c", "d", "e", "f"]
zahlen = [5, 3, 7, 9, 11, 2]
print(zip(buchstaben, zahlen))
<zip object at 0x7f9fd41cb5a0>

Das Ergebnis ist ein zip-Objekt und man ist nicht klüger als zuvor, wenn man zip nicht kennt. Die Anwendung von zip gibt einen Iterator zurück, der in der Lage ist Tupel zu erzeugen. Es werden die ersten Elemente der iterierbaren Parameter (in unseren Beispiel handelt es sich am Listen) zu einem Tupel zusammengefasst, danach werden die zweiten Elemente zusammengefügt, dann die dritten und so weiter. Es stoppt, wenn einer der Parameter am Ende ist, d.h. ss sind keine weiteren Elemente verfügbar.

Der beste Weg, um zu sehen, was die zip-Funktion erstellt, besteht darin, sie in einer for-Schleife zu verwenden.

for t in zip(buchstaben, zahlen):
    print(t)
('a', 5)
('b', 3)
('c', 7)
('d', 9)
('e', 11)
('f', 2)

Wenn Sie sich die Ausgabe oben und das folgende Bild genau ansehen, werden Sie hoffentlich verstehen, warum zip etwas mit einem Reißverschluss zu tun hat und warum sie den Namen gewählt haben.

Zuordnung von zwei Listen zu einem Reißverschluss

zip kann eine beliebige Anzahl von iterierbaren Argumenten haben, wie wir im folgenden Beispiel sehen können:

ort = ["Helgoland", "Kiel", 
       "Berlin-Tegel", "Konstanz", 
       "Hohenpeißenberg"]
luftdruck = [1021.2, 1019.9, 1023.7, 1023.1, 1027.7]
temperaturen = [6.0, 4.3, 2.7, -1.4, -4.4]
höhe = [4, 27, 37, 443, 977]
                
for t in zip(ort, luftdruck, temperaturen, höhe):
    print(t)
('Helgoland', 1021.2, 6.0, 4)
('Kiel', 1019.9, 4.3, 27)
('Berlin-Tegel', 1023.7, 2.7, 37)
('Konstanz', 1023.1, -1.4, 443)
('Hohenpeißenberg', 1027.7, -4.4, 977)

Die Verwendung von zip ist nicht auf Listen und Tupel beschränkt. Es kann natürlich auf alle iterierbaren Objekte wie Listen, Tupel, Zeichenfolgen, Wörterbücher, Mengen, Bereiche und vieles mehr angewendet werden.

lebensmittel = ["Schinken", "Spam", "Käse"]
for artikel in zip(range(1000, 1003), lebensmittel):
    print(artikel)
(1000, 'Schinken')
(1001, 'Spam')
(1002, 'Käse')

Aufruf von zip ohne Argumente

Wir wollen nun schauen, was passiert, wenn wir zip ohne Parameter aufrufen:

for i in zip():
    print("Dies wird nicht gedruckt")

Der Körper der Schleife wurde nicht ausgeführt!

Aufruf von zip mit einem iterierbaren Objekt

Was passiert, wenn wir zip mit nur einem Argument aufrufen, z. einem String:

s = "Python"
for t in zip(s):
    print(t)
('P',)
('y',)
('t',)
('h',)
('o',)
('n',)

Dieser Aufruf erstellt also einen Iterator, der Tupel mit einem einzigen Element erzeugt, in unserem Fall den Zeichen der Zeichenfolge.

Parameter mit unterschiedlichen Längen

Wie wir gesehen haben, kann zip mit einer beliebigen Anzahl von iterierbaren Objekten als Argumente aufgerufen werden. Bisher war die Anzahl der Elemente oder die Länge dieser iterierbaren Objekte gleich gewesen. Dies ist nicht erforderlich. Wenn die Längen unterschiedlich sind, erzeugt zip keine Ausgabe mehr, sobald eine der Argumentsequenzen erschöpft ist. "Erzeugt keine Ausgaben mehr" bedeutet, dass eine StopIteration-Ausnahme ausgelöst wird. Diese Ausnahme wird von der for-Schleife abgefangen. Weitere Informationen zu dieser Arbeitsweise finden Sie im Kapitel "Iteratoren und Iterable" unseres Python-Tutorials.

Das folgende Beispiel ist ein Zip-Anruf mit zwei Listen von unterschiedlichen Längen:

farben = ["green", "red", "blue"]
autos = ["BMW", "Alfa Romeo"]
for auto, farbe in zip(autos, farben):
    print(auto, farbe)
BMW green
Alfa Romeo red

Erweiterte Verwendung von zip

Wir haben eine Liste mit den sechs größten Städten der Schweiz. Sie besteht aus Tupeln mit Paaren, bestehend aus Stadtname und der Bevölkerungszahl:

städte_und_bevölkerung = [("Zurich", 415367),
                         ("Geneva", 201818),
                         ("Basel", 177654),
                         ("Lausanne", 139111),
                         ("Bern", 133883),
                         ("Winterthur", 111851)]

Die Aufgabe besteht darin, zwei Listen zu erstellen: eine mit den Städtenamen und eine mit den Bevölkerungszahlen. zip ist die Lösung für dieses Problem, aber wir müssen auch den Sternoperator verwenden, um die Liste zu entpacken:

städte, bevölkerung = list(zip(*städte_und_bevölkerung))
print(städte)
print(bevölkerung)
('Zurich', 'Geneva', 'Basel', 'Lausanne', 'Bern', 'Winterthur')
(415367, 201818, 177654, 139111, 133883, 111851)

Obiges Vorgehen ist beispielsweise erforderlich, wenn wir diese Daten plotten möchten. Dies ist nur ein anschauliches Beispiel und es ist nicht notwendig, es vollständig zu verstehen. Sie müssen mit Pandas vertraut sein. Im folgenden Programm wird davon ausgegangen, dass zu Beginn nur die kombinierte Liste verfügbar ist:

import pandas as pd
städte_und_bevölkerung = [("Zurich", 415367),
                         ("Geneva", 201818),
                         ("Basel", 177654),
                         ("Lausanne", 139111),
                         ("Bern", 133883),
                         ("Winterthur", 111851)]
städte, bevölkerung = list(zip(*städte_und_bevölkerung))
s = pd.Series(bevölkerung, index=städte)
s.plot(kind="bar")
Ausgabe: :

<matplotlib.axes._subplots.AxesSubplot at 0x7f9fb92b0e50>

Konvertieren von zwei Iterables in ein dictionary

zip bietet uns auch eine hervorragende Möglichkeit, zwei Iterables in ein Dictionary umzuwandeln. Natürlich nur, wenn diese Iterables bestimmte Anforderungen erfüllen. Das Iterable, das als Schlüssel verwendet werden soll, muss eindeutig sein und darf nur aus unveränderlichen Elementen bestehen. Wir demonstrieren dies anhand des folgenden Morsecode-Beispiels. Das vollständige Morsecode-Alphabet finden Sie in unserem Kapitel über Wörterbücher:

abc = "abcdef"
morse_kar = [".-", "-...", "-.-.", "-..", ".", "..-."]
               
text2morse = dict(zip(abc, morse_kar))
print(text2morse)
{'a': '.-', 'b': '-...', 'c': '-.-.', 'd': '-..', 'e': '.', 'f': '..-.'}

Fußnoten

1 ie Daten stammen vom 1. April 2020, kein Scherz. Die Standorte wurden beliebig gewählt. Es gibt jedoch einen besonderen Grund, warum ich mich für Hohenpeißenberg entschieden hatte. Auf dem Hohenpeißenberg wurde ich eingeladen, zwei unvergessliche Python-Kurse für den deutschen Wetterdienst zu geben: Tolle Leute und eine fantastische Aussicht!