Zum Inhalt
wannacode

Schleifen

Kurz gesagt: Eine Schleife wiederholt ein Stück Code, so lange es nötig ist: for mit range geht eine Reihe von Zahlen durch, while wiederholt, solange eine Bedingung wahr ist, und break beendet die Schleife.

Problem

Wie viel sparst du?

Du beschließt zu sparen: Im ersten Monat legst du 10 € zur Seite, im zweiten 20 €, im dritten 30 € und so weiter, jedes Mal 10 € mehr. Wie viel hast du nach 4 Monaten?

total = 0
total += 1 * 10
total += 2 * 10
total += 3 * 10
total += 4 * 10
print(total)
Ausgabe
100

Das funktioniert. Aber nach 3 Jahren sind es 36 Zeilen, fast alle gleich. Und wenn die Zahl der Monate über die Tastatur eingegeben wird, weißt du gar nicht, wie viele Zeilen du schreiben sollst. Du brauchst eine Möglichkeit zu sagen: „Wiederhole das so oft.“

Die Idee

for: für jede Zahl wiederholen

Ein Stück Code, das sich wiederholt, heißt Schleife. Die Schleife, die du am häufigsten brauchst, ist for. Hier sind die Zahlen von 1 bis 10:

for i in range(1, 11):
print(i)
Ausgabe
1
2
3
4
5
6
7
8
9
10

for i in range(1, 11): bedeutet „für jedes i aus den Zahlen, die range liefert“. i ist der Zähler: In jedem Durchlauf bekommt er die nächste Zahl. range hat drei Teile, getrennt durch Kommas:

  • Start: 1. Die erste Zahl. Fehlt sie wie in range(10), ist der Start 0.
  • Ende: 11. Das Ende ist nicht dabei: Die letzte Zahl ist 10. Deshalb geht range(1, 11) von 1 bis 10.
  • Schritt: wie viel jedes Mal dazukommt. Fehlt er, ist er 1. range(3, 0, -1) zählt rückwärts: 3, 2, 1.

Der Rumpf ist das, was nach dem Doppelpunkt um 4 Leerzeichen eingerückt ist, genau wie bei if.

Jede Ausführung des Rumpfs heißt Iteration oder kurz Durchlauf.

Genauer, für Neugierige
  • Der Schritt kann sein, was du brauchst: jede zweite Zahl, rückwärts. Und range(10) zählt von 0 bis 9: immer noch 10 Durchläufe. Warum man ab 0 zählt, wird in der Lektion über Listen klar.
for i in range(1, 11, 2):
print(i, end=" ")
print()
for i in range(10, 0, -1):
print(i, end=" ")
print()
for i in range(10):
print(i, end=" ")
print()
Ausgabe
1 3 5 7 9
10 9 8 7 6 5 4 3 2 1
0 1 2 3 4 5 6 7 8 9
  • In Python gibt es den Zähler auch nach der Schleife noch, mit seinem letzten Wert. In Java, C# und JavaScript ist er nach der Schleife weg.
for i in range(1, 4):
print(i)
print("Nach der Schleife ist i", i)
Ausgabe
1
2
3
Nach der Schleife ist i 3
  • Python hat kein for mit Bedingung und Schritt wie for (int i = 1; i <= 10; i++) in Java. Wenn du „solange etwas wahr ist“ brauchst, gibt es while (kommt gleich).

Sieh es dir an

Durchlauf für Durchlauf

Das sind die Ersparnisse von der ersten Karte, mit einer Schleife. Sieh zu, wie sich month und total ändern.

total = 0
for month in range(1, 5):
total += month * 10
print(total) # 100
Schritt für Schritt, in Worten
  1. total beginnt bei 0.
  2. month = 1, die erste Zahl aus range(1, 5). Es geht in den Rumpf.
  3. Durchlauf 1: total += 1 * 10, total wird 10.
  4. month wird 2, die nächste Zahl aus range. Noch ein Durchlauf, total wird 30.
  5. month 3: total wird 60.
  6. month 4: total wird 100.
  7. range(1, 5) hat keine Zahlen mehr: Das Ende 5 ist nicht dabei. Die Schleife endet, und month bleibt 4.
  8. Nach der Schleife ist total 100.

Der Rumpf ist eine Zeile und steht nur einmal da. Für 36 Monate änderst du nur 5 in 37. Du kannst dort sogar eine Variable einsetzen, die von der Tastatur gelesen wurde.

Probier es aus

Rückwärts zählen

Was gibt das Programm aus?

for sec in range(3, 0, -1):
print(sec)
print("Start!")
Antwort

Die Idee

while: bis das Ende kommt

Manchmal weißt du vorher nicht, wie viele Durchläufe es gibt. Die Kasse liest Preise, bis die Kassiererin 0 eingibt, und nennt dann die Summe. Hier passt for nicht. Es passt while: es wiederholt, solange die Bedingung wahr ist.

total = 0
price = int(input())
while price != 0:
total += price
price = int(input())
print(f"Gesamt: {total} €")
Eingabe
12
4
7
0
Ausgabe
Gesamt: 23 €

Der erste Preis wird vor der Schleife gelesen, damit die Bedingung etwas zu prüfen hat. Der nächste wird am Ende des Rumpfs gelesen. Ist die erste Zahl 0, läuft der Rumpf kein einziges Mal.

Manchmal muss der Rumpf mindestens einmal laufen, und die Bedingung wird erst nach dem Durchlauf geprüft. Zum Beispiel bei einer Frage, die sich wiederholt, bis die Antwort passt. Java, C# und JavaScript haben dafür do-while. Python hat das nicht. Du schreibst while True:, eine Schleife, deren Bedingung immer wahr ist, und darin ein break, das sie beendet, sobald die Antwort passt (mehr zu break gleich):

while True:
print("Wie viele Tickets (1 bis 10)?")
count = int(input())
if 1 <= count <= 10:
break
print(f"Reservierte Tickets: {count}")
Eingabe
0
15
3
Ausgabe
Wie viele Tickets (1 bis 10)?
Wie viele Tickets (1 bis 10)?
Wie viele Tickets (1 bis 10)?
Reservierte Tickets: 3
Genauer, für Neugierige
  • Wenn die Bedingung nie falsch wird, endet die Schleife nie. Das ist eine Endlosschleife: Das Programm „hängt“, und du musst es von Hand stoppen. Die häufigste Ursache ist eine vergessene Änderung der Variable in der Bedingung, zum Beispiel ein fehlendes price = … am Ende des Rumpfs.
  • while True: ohne break darin ist eine Endlosschleife. Achte darauf, dass es einen Weg zum break gibt.
  • Jedes for lässt sich als while schreiben. Du nimmst die Variante, die sich klarer liest: for für eine bekannte Zahl von Durchläufen, while für „bis etwas passiert“.

Probier es aus

Finde den Fehler

Das Programm soll die Zahlen von 1 bis 5 addieren: 1 + 2 + 3 + 4 + 5 = 15. Es gibt 10 aus. In welcher Zeile ist der Fehler?

Wähle die Zeile mit dem Fehler.

Die Summe steht in total, nicht in sum: In Python ist sum der Name einer eingebauten Funktion, und du solltest ihn besser nicht belegen.

Die Idee

break und continue

Zwei Wörter ändern den üblichen Ablauf einer Schleife.

continue überspringt den Rest des aktuellen Durchlaufs und geht zum nächsten. Du listest Termine von 9 bis 17 Uhr auf, aber um 13 Uhr ist Mittagspause:

for hour in range(9, 18):
if hour == 13:
continue
print(f"{hour}:00")
Ausgabe
9:00
10:00
11:00
12:00
14:00
15:00
16:00
17:00

break beendet die ganze Schleife sofort. Du suchst die erste Zahl, durch die 91 teilbar ist. Sobald du sie gefunden hast, hat Weitersuchen keinen Sinn:

n = 91
for d in range(2, n):
if n % d == 0:
print(f"{n} ist durch {d} teilbar")
break
Ausgabe
91 ist durch 7 teilbar
Genauer, für Neugierige
  • break beendet nur die Schleife, in der es steht. Steht es in einer verschachtelten Schleife (nächste Karte), läuft die äußere weiter.
  • while True: mit einem break darin kennst du schon: eine Schleife, die nicht durch ihre Bedingung endet, sondern durch ein break an der richtigen Stelle.

Die Idee

Eine Schleife in einer Schleife

Der Kinosaal hat 3 Reihen mit je 4 Plätzen. Du willst jeden Platz ausgeben. Für jede Reihe gehst du alle Plätze darin durch:

for row in range(1, 4):
for seat in range(1, 5):
print(f"[{row}-{seat}]", end="")
print()
Ausgabe
[1-1][1-2][1-3][1-4]
[2-1][2-2][2-3][2-4]
[3-1][3-2][3-3][3-4]

Das nennt man verschachtelte Schleifen. Die innere Schleife läuft bei jedem Durchlauf der äußeren komplett durch: 3 Reihen · 4 Plätze = 12 Ausgaben. end="" sagt print, dass es nicht in eine neue Zeile springen soll. So bleiben die Plätze in einer Zeile. Das leere print() nach der inneren Schleife springt in eine neue Zeile.

Probier es aus

Treppe

In der ersten Zeile soll ein Stern stehen, in der zweiten zwei, in der vierten vier. Was gehört in die Lücke?

for row in range(1, 5):
    for star in range():
        print("*", end="")
    print()

Die Idee

Zufallszahlen für Spiele

Ein Würfelspiel braucht eine Zahl, die das Programm vorher nicht kennt. random liefert sie dir:

import random
dice = random.randint(1, 6)
print(f"Gewürfelt: {dice}")

random ist ein Modul: fertiger Code, der mit Python kommt. Du holst ihn mit import random ganz oben in der Datei herein, genau wie math.

random.randint(1, 6) liefert eine ganze Zahl von 1 bis 6. Achtung: Hier sind beide Grenzen dabei, anders als bei range.

Jeder Start liefert eine andere Zahl, deshalb gibt es hier keine Ausgabe. Und hier ist eine Schleife, die würfelt, bis eine Sechs fällt:

import random
rolls = 0
while True:
dice = random.randint(1, 6)
rolls += 1
if dice == 6:
break
print(f"Sechs nach {rolls} Würfen")
Genauer, für Neugierige
  • Wenn du mit random.seed(42) einen Startwert setzt, liefert jeder Start dieselbe Folge. Das hilft beim Testen.
  • random.random() liefert eine Kommazahl von 0 bis 1 (ohne 1), wie Math.random() in JavaScript.
  • Die Zahlen sind nicht wirklich zufällig: Sie werden mit einer Formel berechnet. Für Spiele reichen sie, für Passwörter und Sicherheit nicht.

Übung

Aufgaben zu Schleifen

Löse die Aufgaben in deinem Editor. Zu jeder gibt es eine Beispiel-Eingabe und -Ausgabe, mit der du deine vergleichen kannst. Die Zahl liest du genauso ein wie in der Lektion „Eingabe und Ausgabe“.

1. Einmaleins. Lies eine Zahl ein und gib ihre Produkte mit den Zahlen von 1 bis 10 aus.

Eingabe
7
Ausgabe
7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
7 x 6 = 42
7 x 7 = 49
7 x 8 = 56
7 x 9 = 63
7 x 10 = 70

2. Primzahl. Eine Zahl ist eine Primzahl, wenn sie nur durch 1 und durch sich selbst teilbar ist: 2, 3, 5, 7, 11… Lies eine Zahl ein und gib aus, ob sie eine Primzahl ist. Tipp: Probiere die Teiler ab 2 aufwärts und hör beim ersten mit break auf.

Eingabe
91
Ausgabe
91 ist keine Primzahl

Für 11 ist die Ausgabe „11 ist eine Primzahl“.

3. Die Ziffern einer Zahl. Lies eine positive ganze Zahl ein. Gib sie rückwärts aus und dazu die Summe ihrer Ziffern. Tipp: n % 10 ist die letzte Ziffer, und n // 10 entfernt die letzte Ziffer. Wiederhole das, bis die Zahl 0 wird.

Eingabe
2024
Ausgabe
Umgekehrt: 4202
Quersumme: 8

4. Zahlenraten. Der Computer „denkt sich“ eine Zahl von 1 bis 100 aus, und du suchst sie. Nach jedem Versuch sagt das Programm „Die Zahl ist kleiner.“ oder „Die Zahl ist größer.“ und am Ende, wie viele Versuche du gebraucht hast. Schreib es zuerst mit der geheimen Zahl 37, damit du es mit dem Beispiel vergleichen kannst:

Eingabe
50
25
37
Ausgabe
Die Zahl ist kleiner.
Die Zahl ist größer.
Richtig! Du hast 3 Versuche gebraucht.

Wenn es funktioniert, ersetze 37 durch eine Zufallszahl von 1 bis 100. Jetzt kennst nicht einmal du die Antwort.

Weitere Aufgaben

  • Von 1 bis N. Lies N ein und gib die Zahlen von 1 bis N in einer Zeile aus. Für 5: 1 2 3 4 5.
  • Fakultät. N! = 1 · 2 · 3 · … · N. Für 5: 120. In Python hat eine ganze Zahl keine obere Grenze: 20! ist 2432902008176640000, und 30! wird genauso exakt berechnet.
  • Primzahlen bis N. Gib alle Primzahlen bis N aus. Für 20: 2 3 5 7 11 13 17 19. Die Prüfung aus Aufgabe 2 kommt in eine Schleife über die Zahlen: verschachtelte Schleifen.
  • Fibonacci. Jede Zahl ist die Summe der beiden davor: 0, 1, 1, 2, 3, 5, 8… Lies N ein und gib die ersten N Zahlen aus. Für 10: 0 1 1 2 3 5 8 13 21 34.
  • Quadrat aus Sternen. Lies N ein und gib ein Quadrat N × N aus. Für 3:
Ausgabe
* * *
* * *
* * *
  • Dreieck aus Sternen. Dasselbe, aber jede Zeile hat so viele Sterne wie ihre Nummer. Für 3:
Ausgabe
*
* *
* * *
  • Münzwurf. Lies N ein, wirf N-mal eine Münze mit einer Zufallszahl (0 ist Kopf, 1 ist Zahl) und gib aus, wie oft jede Seite gefallen ist. Je größer N ist, desto näher kommen beide Zahlen an N / 2.
  • Schere, Stein, Papier. Ein Spieler gegen den Computer. Der Spieler gibt seine Wahl ein, der Computer wählt zufällig, und das Programm sagt, wer gewinnt. Mit while True und break fragt es „Noch ein Spiel? (ja/nein)“ und gibt am Ende den Spielstand aus.

Test

Teste dich

1. Wie oft läuft der Rumpf von for i in range(5):?
2. Python hat kein do-while. Wie schreibst du eine Schleife, deren Rumpf mindestens einmal läuft?
3. Was macht continue?
4. Die äußere Schleife läuft 3-mal, die innere 4-mal. Wie oft läuft der Rumpf der inneren Schleife?
5. Welche Zeile liefert eine Zufallszahl von 1 bis 6?

Erstellt von Ivo Gergov im Rahmen der Kampagne von Evo Tech für zugängliche Programmierausbildung ·