6.2 Schleifen 

Eine sogenannte Schleife ermöglicht es ganz allgemein, einen Codeblock, den sogenannten Schleifenkörper, mehrmals hintereinander auszuführen. Python unterscheidet zwei Typen von Schleifen: eine while-Schleife als sehr simples Konstrukt und eine for-Schleife zum Durchlaufen komplexerer Datentypen.
6.2.1 While-Schleife 

Die while-Schleife haben wir bereits in unserem Spiel »Zahlenraten« verwendet. Sie dient dazu, einen Codeblock so lange auszuführen, wie eine bestimmte Bedingung erfüllt ist. In unserem ersten Programm aus Abschnitt 5.2 wurde mithilfe einer while-Schleife so lange eine neue Zahl vom Spieler eingelesen, bis die eingegebene Zahl mit der gesuchten Zahl übereinstimmte.
Grundsätzlich besteht eine while-Schleife aus einem Schleifenkopf, in dem die Bedingung steht, sowie einem Schleifenkörper, der dem auszuführenden Codeblock entspricht. Beachten Sie, dass die Schleife läuft, solange die Bedingung erfüllt ist, und nicht, bis sie erfüllt ist.
Abbildung 6.5 Struktur einer while-Schleife
Das folgende Beispiel ist ein etwas verknappter Ausschnitt des »Zahlenraten«-Spiels und soll die Verwendung der while-Schleife veranschaulichen:
secret = 1337 guess = 0 while guess != secret: guess = input("Raten Sie: ")
Das Schlüsselwort while leitet den Schleifenkopf ein und wird von der gewünschten Bedingung und einem Doppelpunkt gefolgt. In den nächsten Zeilen folgt, um eine Stufe weiter eingerückt, der Schleifenkörper. Dort wird eine Zahl vom Benutzer eingelesen und mit dem Namen guess versehen. Dieser Prozess läuft so lange, bis die im Schleifenkopf genannte Bedingung erfüllt ist, bis also die Eingabe des Benutzers (guess) mit der geheimen Zahl (secret) übereinstimmt.
Ähnlich wie eine if-Anweisung kann eine while-Schleife um einen else-Zweig erweitert werden. Der Codeblock, der zu diesem Zweig gehört, wird genau einmal ausgeführt, nämlich dann, wenn die Schleife vollständig abgearbeitet wurde, also die Bedingung zum ersten Mal False ergibt:
Abbildung 6.6 Struktur einer while-Schleife mit else-Zweig
Betrachten wir dies an einem konkreten Beispiel:
secret = 1337 guess = 0 while guess != secret: guess = input("Raten Sie: ") else: print "Sie haben es geschafft!"
Aus Benutzersicht bedeutet dies, dass die Erfolgsmeldung ausgegeben wird, wenn die richtige Zahl geraten wurde:
Raten Sie: 100 Raten Sie: 200 Raten Sie: 1337 Sie haben es geschafft!
Momentan scheint dieser else-Zweig überflüssig, da der gleiche Effekt durch folgenden Code erreicht werden kann:
secret = 1337 guess = 0 while guess != secret: guess = input("Raten Sie: ") print "Sie haben es geschafft!"
Die beiden Beispiele sind in diesem Anwendungsfall völlig äquivalent zu verwenden. Dies ist nicht immer der Fall. Dass der else-Zweig einer while-Schleife durchaus seine Berechtigung hat, werden Sie im nächsten Abschnitt sehen.
6.2.2 Vorzeitiger Abbruch einer Schleife 

Stellen Sie sich einmal vor, wir wollten das Beispiel, das wir im vorherigen Abschnitt eingeführt haben, dahingehend erweitern, dass das Spiel durch Eingabe einer 0 beendet werden kann. Dies ist mit Ihrem bisherigen Kenntnisstand zwar möglich, jedoch nur über Umwege zu erreichen. Was wirklich fehlt, ist eine Möglichkeit, eine Schleife in besonderen Fällen vorzeitig zu beenden. Genau dies wird mit der sogenannten break-Anweisung erreicht:
secret = 1337 guess = 0 while guess != secret: guess = input("Raten Sie: ") if guess == 0: print "Das Spiel wird beendet" break else: print "Sie haben es geschafft!"
Das Beispiel wurde durch eine if-Anweisung erweitert. Direkt nachdem eine Zahl vom Spieler eingegeben und mit dem Namen guess versehen wurde, wird geprüft, ob es sich bei der Eingabe um eine 0 handelt (guess == 0). Sollte dies der Fall sein, wird eine entsprechende Meldung ausgegeben und die while-Schleife mittels break beendet.
In Kombination mit break zeigt sich auch die eigentliche Bedeutung des else-Zweigs einer Schleife. Der else-Zweig wird nur ausgeführt, wenn die Schleife vollständig durchlaufen wurde, und nicht, wenn sie durch break vorzeitig beendet wurde. Das Ablaufprotokoll gibt uns hier recht:
Raten Sie: 100 Raten Sie: 200 Raten Sie: 0 Das Spiel wird beendet
6.2.3 Vorzeitiger Abbruch eines Schleifendurchlaufs 

Wir haben mit break bereits eine Möglichkeit vorgestellt, den Ablauf einer Schleife zu beeinflussen. Die sogenannte continue-Anweisung bricht im Gegensatz zu break jedoch nicht die gesamte Schleife ab, sondern nur den aktuellen Schleifendurchlauf. Um dies zu veranschaulichen, betrachten wir das folgende Beispiel, das bisher noch ohne continue-Anweisung auskommt:
while True: zahl = input("Geben Sie eine Zahl ein: ") ergebnis = 1 while zahl > 0: ergebnis = ergebnis * zahl zahl = zahl - 1 print "Ergebnis: ", ergebnis
Zur Erklärung des Beispiels: In einer Endlosschleife, also einer while-Schleife, deren Bedingung unter allen Umständen erfüllt ist (while True), wird eine Zahl eingelesen und die Variable ergebnis mit 1 initialisiert. In einer darauf folgenden weiteren while-Schleife wird ergebnis so lange mit zahl multipliziert, wie die Bedingung zahl > 0 erfüllt ist. Zudem wird in jedem Durchlauf der inneren Schleife der Wert von zahl um 1 verringert.
Nachdem die innere Schleife durchlaufen ist, wird die Variable ergebnis ausgegeben. Wie Sie vermutlich bereits erkannt haben, berechnet das Beispielprogramm die Fakultät einer jeden eingegebenen Zahl:
Geben Sie eine Zahl ein: 4 Ergebnis: 24 Geben Sie eine Zahl ein: 5 Ergebnis: 120 Geben Sie eine Zahl ein: 6 Ergebnis: 720
Allerdings erlaubt der obige Code auch eine solche Eingabe:
Geben Sie eine Zahl ein: -10 Ergebnis: 1
Durch die Eingabe einer negativen Zahl ist die Bedingung der inneren Schleife (zahl > 0) von vornherein False, die Schleife wird also gar nicht erst ausgeführt. Aus diesem Grund wird sofort der Wert von ergebnis ausgegeben, der in diesem Fall 1 ist.
Das ist allerdings nicht ganz das, was in diesem Fall erwartet werden würde. Bei einer negativen Zahl handelt es sich um eine ungültige Eingabe. Idealerweise sollte das Programm also bei Eingabe einer ungültigen Zahl die Berechnung abbrechen und kein Ergebnis anzeigen. Eben dies wird durch Verwendung einer continue-Anweisung erreicht:
while True: zahl = input("Geben Sie eine Zahl ein: ") if zahl < 0: print "Negative Zahlen sind nicht erlaubt" continue ergebnis = 1 while zahl > 0: ergebnis = ergebnis * zahl zahl = zahl - 1 print "Ergebnis: ", ergebnis
Direkt nachdem die Eingabe des Benutzers eingelesen wurde, wird in einer if-Abfrage überprüft, ob es sich um eine negative Zahl handelt (zahl < 0). Sollte das der Fall sein, so wird mittels print eine entsprechende Fehlermeldung ausgegeben und der aktuelle Schleifendurchlauf mit continue abgebrochen. Das heißt, dass alle Codezeilen, die zur Schleife gehören und hinter continue stehen, erst im nächsten Schleifendurchlauf wieder interpretiert werden. Aus Benutzersicht bedeutet das, dass nach Eingabe einer negativen Zahl kein Ergebnis, sondern eine Fehlermeldung ausgegeben wird. Danach wird zur Eingabe der nächsten Zahl aufgefordert:
Geben Sie eine Zahl ein: 4 Ergebnis: 24 Geben Sie eine Zahl ein: 5 Ergebnis: 120 Geben Sie eine Zahl ein: -10 Negative Zahlen sind nicht erlaubt Geben Sie eine Zahl ein: -100 Negative Zahlen sind nicht erlaubt
Abbildung 6.7 Eine Schleife mit break und continue
Rückblickend möchten wir an dieser Stelle noch einmal den Unterschied zwischen break und continue herausarbeiten (siehe Abbildung 6.7).
Während break die Schleife vollständig abbricht, beendet continue nur den aktuellen Schleifendurchlauf, die Schleife an sich läuft aber weiter.
6.2.4 For-Schleife 

Neben der bisher behandelten while-Schleife existiert in Python ein weiteres Schleifenkonstrukt, die sogenannte for-Schleife. Eine for-Schleife kann im einfachsten Fall als Zählschleife verwendet werden. Das ist eine Schleife, die es dem Programmierer ermöglicht, festzulegen wie oft ein Codeblock erneut ausgeführt werden soll. Die Anzahl der bisherigen Schleifendurchläufe steht im Codeblock als Variable, dem sogenannten Schleifenzähler, zur Verfügung (siehe Abbildung 6.8).
Abbildung 6.8 Struktur einer for-Schleife
Was genau für Objekt eingesetzt werden kann, werden wir im Folgenden erklären. Konkret im Quelltext sieht eine for-Schleife beispielsweise so aus:
for i in range(5): print i
In diesem Beispiel werden alle ganzen Zahlen von 0 bis einschließlich 4 ausgegeben. range kann dabei nicht nur ein Limit setzen, sondern allgemein in drei Varianten verwendet werden:
range(stop) range(start, stop) range(start, stop, step)
Der Platzhalter start steht dabei für die Zahl, mit der begonnen wird. Die Schleife wird beendet, sobald stop erreicht wurde. Wichtig ist zu wissen, dass der Schleifenzähler selbst niemals den Wert stop erreicht, er bleibt stets kleiner. In jedem Schleifendurchlauf wird der Schleifenzähler um step erhöht. Sowohl start als auch stop und step müssen ganze Zahlen sein. Wenn alle Werte angegeben sind, sieht die for-Schleife folgendermaßen aus:
for i in range(1, 10, 2): print i
Die Zählvariable i beginnt jetzt mit dem Wert 1, die Schleife wird ausgeführt, solange i kleiner ist als 10, und in jedem Schleifendurchlauf wird i um 2 erhöht. Damit gibt die Schleife die Werte 1, 3, 5, 7 und 9 auf dem Bildschirm aus.
Eine for-Schleife kann nicht nur in positiver Richtung verwendet werden, es ist auch möglich, herunterzuzählen:
for i in range(10, 1, -2): print i
In diesem Fall wird i zu Beginn der Schleife auf den Wert 10 gesetzt und in jedem Durchlauf um 2 verringert. Die Schleife läuft, solange i größer ist als 1, und würde die Werte 10, 8, 6, 4 und 2 auf dem Bildschirm ausgeben.
Damit bietet sich die for-Schleife geradezu an, um das Beispiel des letzten Abschnitts zur Berechnung der Fakultät einer Zahl zu überarbeiten. Es ist gleichzeitig ein Beispiel dafür, dass while- und for-Schleifen wie selbstverständlich ineinander verwendet werden können:
while True: zahl = input("Geben Sie eine Zahl ein: ") if zahl < 0: print "Negative Zahlen sind nicht erlaubt" continue ergebnis = 1 for i in range(2, zahl+1): ergebnis = ergebnis * i print "Ergebnis: ", ergebnis
Nachdem eine Eingabe durch den Benutzer erfolgt ist und diese auf ihr Vorzeichen hin überprüft wurde, wird eine for-Schleife eingeleitet. Der Schleifenzähler i der Schleife beginnt mit dem Wert 2. Die Schleife läuft, solange i kleiner als zahl+1 ist: Der höchstmögliche Wert von i ist also zahl. In jedem Schleifendurchlauf wird dann die Variable ergebnis mit i multipliziert.
Es wurde bereits angedeutet, dass eine Zählschleife nur eine mögliche Verwendung der for-Schleife darstellt. Ganz allgemein durchläuft eine for-Schleife ein sogenanntes iterierbares Objekt. Ohne näher ins Detail gehen zu wollen, ist zu sagen, dass ein solches Objekt in der Regel eine Art Container für eine Reihe verschiedener Werte darstellt. Sie werden im Laufe dieses Buchs viele solcher Objekte kennenlernen, und wir werden dabei jedes Mal auf die Verwendung der for-Schleife zurückkommen.
Eines dieser iterierbaren Objekte haben Sie jedoch bereits kennengelernt: Ein String kann ganz allgemein als ein Container für eine Reihe von Buchstaben betrachtet werden, und als solcher auch mithilfe der for-Schleife durchlaufen werden. Der Vorgang wird auch Iterieren genannt. Es wird »über einen String iteriert«:
for c in "Hallo Welt": print c
Die Ausgabe dieses Beispiels lautet:
H a l l o W e l t
Der Namenswechsel der Schleifenvariable von i nach c hat übrigens keine syntaktische Bedeutung, sondern eher eine assoziative: i kann als Abkürzung für »integer« (dt. ganze Zahl) und c für »character« (dt. Buchstabe) angesehen werden.
Dass jeder Buchstabe in eine neue Zeile geschrieben wurde, hat nichts mit der Schleife zu tun, sondern ist ein normales Verhalten der print-Anweisung.
Abschließend ist noch zu sagen, dass eine for-Schleife genauso über einen else-Zweig verfügen kann wie eine while-Schleife. Auch bei einer for-Schleife ist ein else-Zweig nur in Kombination mit break sinnvoll (siehe Abbildung 6.9).
Konkret:
for c in "abc": print c else: print "abc"
Abbildung 6.9 Struktur einer for-Schleife mit else-Zweig
Dies führt zu folgender Ausgabe:
a b c abc