For-Loops in Python#

Ungefähr so wie in dem obigen Beispiel funktionieren auch For-Loops in Python. Wir haben immer eine Menge an Elementen (z.B. in einer Liste) und geben dann an, was wir mit bzw. für jedes Element machen wollen. Oben war die Menge an Elementen eben der Inhalt der Chipstüte und dann haben wir angegeben, was mit jedem bzw. für jeden Chip gemacht wird. Das Gute ist, dass so ähnlich, wie wir den Chipstüten-For-Loop aufgeschrieben haben, auch For-Loops in Python aufgeschrieben werden. Allgemein und abstrakt formuliert sieht ein For-Loop in Python immer so aus:

for ELEMENT in MENGE:
    IRGENDEINE_AKTION

Zunächst einmal würde Python hier erwarten, dass das Objekt MENGE ein sogenanntes iterierbares Objekt ist. Das bedeutet erstmal ganz einfach formuliert, dass dieses Objekt eine Reihe von Elementen enthält, die innerhalb eines For-Loops überhaupt durchgegangen werden könnten. Ist das der Fall, dann würde Python bei diesem For-Loop jedes “ELEMENT” der “MENGE” durchgehen und für jedes “ELEMENT” den Code “IRGENDEINE_AKTION” ausführen. ELEMENT, MENGE und IRGENDEINE_AKTION sind natürlich nur Platzhalter für in unserem Programm wirklich existierende Python-Objekte und “Aktionen”.

Werden wir mal etwas konkreter und schauen uns For-Loops an einem richtigen Beispiel in Python an. Angenommen wir haben eine Liste mit Wörtern und würden gerne die Länge jeden Wortes in dieser Liste messen. Im Folgenden erstelle ich zunächst diese Liste mit Wörtern und nenne sie list_of_words.

list_of_words = [
    "Kraftfahrzeug-Haftpflichtversicherung", 
    "Donau-Dampfschifffahrtsgesellschaft", 
    "psychophysicotherapeutics", 
    "Arbeiterunfallversicherungsgesetz",
    "pneumonoultramicroscopicsilicovolcanoconiosis",
]

list_of_words
['Kraftfahrzeug-Haftpflichtversicherung',
 'Donau-Dampfschifffahrtsgesellschaft',
 'psychophysicotherapeutics',
 'Arbeiterunfallversicherungsgesetz',
 'pneumonoultramicroscopicsilicovolcanoconiosis']

Die Liste list_of_words ist erstellt und die Wörter sind so lang, dass wir keine Lust haben, die Länge der Wörter jeweils selbst zu zählen. Wie gut, dass es in Python die Funktion len() gibt, welche die Länge eines Objektes misst. Wenden wir die Funktion len() zusammen mit Listindizierung und der Funktion print() an, dann können wir ganz entspannt die Länge eines jeden Wortes in unserer Liste list_of_words ausgeben lassen. Wir müssen einfach nur den folgenden Code eintippen:

print(len(list_of_words[0]))
print(len(list_of_words[1]))
print(len(list_of_words[2]))
print(len(list_of_words[3]))
print(len(list_of_words[4]))
37
35
25
33
45

HALT STOPP!!! Genau das ist ein Beispiel für “repetitives” Programmieren und somit etwas, was wir mit For-Loops verhindern können! Im Grunde wird ja im obigen Code in jeder Zeile derselbe Code angewendet: In jeder Zeile wird per Listenindizierung zunächst auf ein Element der Liste list_of_words zugegriffen, dann die Länge dieses Elements gemessen und schließlich mit der Funktion print() die gemessene Länge geprintet. Genau dafür gibt es For-Loops!

Wie sieht der For-Loop für dieses Beispiel aus? Statt

für jeden Chip in Chipstüte:

oder

for ELEMENT in MENGE:

schreiben wir nun

for word in list_of_words:

und statt der Aktion Chip essen bzw. IRGENDEINE_AKTION führen wir nun die beiden Funktionen print() und len() auf das jeweilige word aus. Insgesamt ergibt sich somit folgender For-Loop:

for word in list_of_words:
    print(len(word))
37
35
25
33
45

Na das ist ja praktisch! Wir bekommen dasselbe Ergebnis wie oben, müssen aber deutlich weniger tippen. Python ist nun nacheinander jedes word in der Liste list_of_words durchgegangen und hat für jedes word die Funktionen len() und print() auf das word angewendet.

Die Schleifenvariable#

Wichtig ist bei dem obigen Beispiel noch zu wissen, dass der Name word nicht durch Python vorgegeben ist, sondern ich frei gewählt habe. Das Wort word ist in diesem Fall die sogenannte Schleifenvariable. Die Schleifenvariable ist bei einem For-Loop in Python immer das Wort, das hinter dem Schlüsselwort for steht. Diese Schleifenvariable kann von uns, genau wie jede andere Variable, fast beliebig benannt werden. Doch was ist eine Schleifenvariable?

Ein For-Loop geht ja immer eine Menge von Elementen Schritt für Schritt von vorne nach hinten durch. Und dabei repräsentiert die Schleifenvariable immer genau das spezifische Element, auf das der For-Loop in dieser Runde gerade zugreift und für welches er gerade eine “Aktion” ausführt. Stell dir vor, du nimmst nacheinander die Chips aus der Chipstüte. Die Schleifenvariable repräsentiert dabei immer genau den Chip, den du gerade in der Hand hälst, sodass du mit diesem irgendetwas machen kannst (z.B. essen). In jeder Runde des For-Loops d.h. für jedes “in die Chipstüte greifen”, steht die Schleifenvariable für einen anderen “Chip”.

Ein Beispiel: Wir haben die Liste [0, 1, 2, 3]. Diese gehen wir mittels For-Loop einmal von vorne nach hinten durch und rufen jedes Element auf. Diesmal nennen wir unsere Schleifenvariable i. Für jedes Element in der Liste [0, 1, 2, 3] führen wir den Code print("Die Schleifenvariable hat den Wert:", i) aus. Da i in jeder Runde neu definiert wird und immer den Wert des jeweils aufgerufenen Elements annimmt, variiert der Output an der Stelle, an der die Variable i aufgerufen wird.

for i in [0, 1, 2, 3]:
    print("Die Schleifenvariable hat den Wert:", i)
Die Schleifenvariable hat den Wert: 0
Die Schleifenvariable hat den Wert: 1
Die Schleifenvariable hat den Wert: 2
Die Schleifenvariable hat den Wert: 3

In jeder Runde des For-Loops wird i durch das jeweilige Element der Liste ersetzt. Wir weisen also dem Variablennamen i praktisch in jeder Runde des For-Loops den Wert des jeweiligen Elements der Liste zu. Das ist eben in der ersten Runde die 0, in der zweiten Runde die 1, in der dritten Runde die 2 und in der vierten Runde die 3.

Zum einen ermöglicht uns das nach und nach auf jedes Element der Liste zuzugreifen, indem es der Schleifenvariable zugewiesen wird - ganz egal, ob wir die Schleifenvariable Chip, word oder i nennen. Zum anderen ermöglicht uns die Schleifenvariable eine gewisse Variation in den For-Loop einzubauen, denn mit jedem Element, auf das der For-Loop zugreift, wechselt der Wert der Schleifenvariable. Dadurch wird in jeder Runde des For-Loops die Aktion für ein anderes Element ausgeführt. Daher führen wir innerhalb eines For-Loops eigentlich auch immer nur “strukturell” bzw. “abstrakt” gleichen Code aus, die konkreten Variablenwerte können sich durchaus pro Runde ändern. Wir essen ja niemals immer wieder genau denselben Chip, sondern immer wieder einen anderen. Und ein Chip ist auch nie in Gänze gleich einem anderen Chip in der Chipstüte, dennoch können wir alle essen.

Zwar muss man die Schleifenvariable bei einem For-Loop immer angeben, wir können sie aber danach im wiederholt ausgeführten Code-Block des For-Loops auch vollkommen ignorieren, so wie ich das hier tue:

numbers = [1, 3, 1, 4]
for n in numbers:
    print("Dies hier hat nichts mit dem Wert der Schleifenvariable zu tun.")
Dies hier hat nichts mit dem Wert der Schleifenvariable zu tun.
Dies hier hat nichts mit dem Wert der Schleifenvariable zu tun.
Dies hier hat nichts mit dem Wert der Schleifenvariable zu tun.
Dies hier hat nichts mit dem Wert der Schleifenvariable zu tun.

Das ist praktisch, wenn man einfach ein und denselben Code X-mal ausführen möchte, ohne sich dabei wirklich für die Elemente in einer Liste zu interessieren. Wir brauchen die Liste aber, um anzugeben, wie viele Runden der Loop haben soll. Die Anzahl der Runden entspricht dann einfach der Länge der angegebenen Liste. Das ist ungefähr so, als würden wir für jeden Chip in einer Chipstüte einmal in die Hände klatschen ohne sonst noch irgendwas mit dem Chip zu machen. Die Anzahl der Chips in der Chipstüte bestimmt dann, wie oft wir in die Hände klatschen. Weitere Auswirkungen haben die konkreten Chips in der Chipstüte dann aber nicht auf uns. Die Chips in der Chipstüte sind also nur ein Vorwand, um irgendeine Aktion zu wiederholen.

Tatsächlich kommt dieser Fall, dass wir die Liste bzw. irgendeine Menge an Elementen nur brauchen, um die Wiederholungsanzahl des For-Loops festzulegen, ziemlich häufig vor. Dann ist es aber ziemlich unpraktisch, jedes mal eine Liste mit der richtigen Länge im For-Loop anzugeben. Stell dir vor, wir wollen einen For-Loop mit 1000 Runden ausführen. Dann müssen wir eine Liste der Länge 1000 angeben. An dieser Stelle wird eine Funktion namens range() nützlich, mit welcher wir “Listen” einer beliebigen Länge unkompliziert und kompakt erstellen können. Diese Funktion schauen wir uns gleich weiter unten an. Vorher werfen wir aber noch kurz einen Blick auf eine andere wichtige Sache bei For-Loops.

Verrückter Code#

Bestimmt ist dir aufgefallen, dass ich den Code-Block eines For-Loops, in welchem die zu wiederholende “Aktion” definiert wird (wie z.B. “Chip essen”), immer etwas nach rechts eingerückt habe. Dieses Einrücken dient nicht nur der Übersichtlichkeit für uns Menschen, sondern wird von Python auch explizit gelesen und ist daher in einem For-Loop absolut notwendig. Python erwartet unter der Kopf-Zeile eines For-Loops, also einer Zeile der Form for ELEMENT in MENGE: immer mindestens eine Zeile, die eine Tab-Breite (4 Leerzeichen) weiter nach rechts eingerückt ist. Wenn das nicht der Fall ist, dann entsteht ein Fehler, wie man hier sieht:

for word in list_of_words:
print(len(word))
  File "<ipython-input-6-66deb0d4d4f6>", line 2
    print(len(word))
        ^
IndentationError: expected an indented block

Python liest jede Zeile, die nach der “For-Loop-Kopfzeile” kommt und eine Tab-Breite eingerückt ist, als Aktions-Teil dieses For-Loops. Durch das Einrücken können wir Python dann auch sagen, dass mehrere Zeilen Teil des Loops sein sollen und somit in jeder Runde des For-Loops bzw. für jedes Element ausgeführt werden sollen. Im folgenden Code sind z.B. zwei Zeilen im “Aktions-Teil” des For-Loops:

for word in list_of_words:
    word_length = len(word)
    print(word_length)
37
35
25
33
45

Mit der ersten Code-Zeile, die nicht mehr in Bezug zur Kopfzeile des For-Loops eingerückt ist, endet der zum For-Loop zugehörige Code. Im Folgenden zwei Beispiele dafür: Im ersten Beispiel ist der Befehl print("yo yo yo") eingerückt, im zweiten Beispiel ist dieser nicht eingerückt. Einmal wird print("yo yo yo") daher als Teil des Loops gelesen und mehrmals wiederholt und einmal wird print("yo yo yo") einfach als neue Code-Zeile nach dem Loop gelesen und daher nur einmal ausgeführt. Das Einrücken des Codes macht daher einen bedeutenden Unterschied in Python!

for word in list_of_words:
    word_length = len(word)
    print(word_length)
    print("yo yo yo")
37
yo yo yo
35
yo yo yo
25
yo yo yo
33
yo yo yo
45
yo yo yo
for word in list_of_words:
    word_length = len(word)
    print(word_length)
print("yo yo yo")
37
35
25
33
45
yo yo yo