Python – 06 While-Schleifen

Python – 06 While-Schleifen

while-Schleifen

Voraussetzungen

Bevor du mit diesem Modul startest, solltest du bereits vertraut sein mit:

Einführung

while-Schleifen sind anders als for-Schleifen nicht von Anfang an terminiert, das heißt die Anzahl der Durchläufe ist nicht per se vorgegeben. Stattdessen läuft die Schleife solange, bis eine bestimmte Bedingung erfüllt ist.

Schauen wir uns ein Beispiel an:

1
2
3
4
5
status = "" #Startwert, damit die erste Prüfung fehlerfrei stattfinden kann

while status != "stop": #Bedingung, hier: Ist status ungleich "stop"? Falls ja, weiter!
    status = input("Ich frage dich solange, bis du 'stop' eingibst.") #neuer Wert für status per input()
print("Programm beendet!") #diese Ausgabe kommt nach der while-Schleife

Beachte bitte folgende Eigenschaften bzw. Kriterien:

  • Die erste Prüfung der Bedingung muss erfolgen können. Deshalb ist in diesem Beispiel status erst ein mal mit einem leeren String übergeben. So kann in der while-Schleife geprüft werden, ob status den Wert hat, der zum Abbruch der Schleife führen soll. Du würdest sofort eine Fehlermeldung erhalten, weil status nicht definiert wäre.
  • Der Block in der while-Schleife wird so lange durchlaufen, bis die Bedingung erfüllt ist. Da muss aber nicht immer ein != als Operator eingesetzt werden. Auch andere Operatoren sind zulässig, wichtig ist nur, dass die Abfrage insgesamt True oder False zurückgibt.
    • Wenn status einen Wert ungleich “stop” hat, dann ist der Wert der Bedingung status != “stop” also True, weil die Bedingung fragt “Ist der Wert ungleich stop?” – “Ja (= True), ist er!”.
    • Wenn status einen Wert gleich “stop” hat, dann ist der Wert der Bedingung status != “stop” also False, weil die Bedingung fragt “Ist der Wert ungleich stop?” – “Nein (= False), ist er nicht!”.

Wann sollte man while-Schleifen nutzen?

while-Schleifen eignen sich bestens dafür, Fallunterscheidungen in einem Zug zu prüfen, auch hier schauen wir uns ein Beispiel an. Aus den Übungen zu if-else-Bedingungen kennen wir diesen Code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
print('Willkommen zu meinem Ratespiel! Ich werde erraten, woran du denkst! Denke an ein Auto, einen Bär oder einen Menschen! Gib bitte immer ein ja oder nein als Antwort ein!\n')

aw = input('Ist es lebendig?\n')

if aw == 'nein':
    print('Es ist das Auto!\n')
else:
    if aw == 'ja':
        aw = input('Hat es vier Beine?\n')
        if aw == 'ja':
            print('Es ist der Bär!')
        else:
            print('Es ist der Mensch!\n')

Wenn du bei diesem Beispiel etwas anders als exakt “ja” oder “nein” eingibst, verlässt du den if-else-Block ohne Ausgabe. Jetzt ergänzen wir Prüfungsstrukturen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#für mehr Übersicht bereiten wir ein paar Stringvariablen vor, die wir dann einfach einsetzen
ersterGruß = 'Willkommen zu meinem Ratespiel! Ich werde erraten, woran du denkst! Denke an ein Auto, einen Bär oder einen Menschen! Gib bitte immer ein ja oder nein als Antwort ein!\n'
fehlermeldung = "--- Fehler --- \n"+"Schreibe exakt 'ja' oder 'nein'. Also bitte noch mal:\n"

fehler = 1 #Prüfvariable am Anfang 1

while fehler == 1: #solange ein Fehler vorliegt, wiederholt sich die Schleife
    print(ersterGruß)
    aw = input("Ist es lebendig?")
    if aw == 'nein':
        fehler = 0 #kein Fehler
        print('Es ist das Auto!\n')
    elif aw == 'ja':
        aw = input('Hat es vier Beine?\n')
        if aw == 'ja':
            fehler = 0 #kein Fehler
            print('Es ist der Bär!')
        elif aw == "nein":
            fehler = 0 #kein Fehler --> verlasse nach diesem Block die Schleife
            print('Es ist der Mensch!\n')
        else:
            fehler = 1 #Fehler --> wiederhole Schleife
            print(fehlermeldung)
    else:
        fehler = 1 #Fehler --> wiederhole Schleife
        print(fehlermeldung)

Besonders wichtig ist die Zeile mit fehler = 1, hier nimmt die Prüfungsvariable den Wert 1 an. Damit wird der Anweisungsblock in der while-Schleife erneut durchlaufen, eben solange ein Fehler existiert. In den anderen Anweisungsblöcken, in die ich mit einer gültigen Bedingung hineingelangt bin, wird der fehler = 0 gesetzt. Damit ist dann aber die Bedingung der while-Schleife nicht mehr erfüllt, deshalb kann ich sie verlassen.

while-Schleifen statt for-Schleifen

Es ist möglich, statt einer for-Schleife einfach eine while-Schleife zu konstruieren

Aufgaben

Aufgabe 1: while vs for

1
2
3
4
5
6
7
8
9
# Beispiel 1
k = 0
while k < 10:
  print(k)
  k += 1 #diese Stelle ist sehr wichtig! Ansonsten läuft dein Code endlos!

#Beispiel 2
for i in range(10):
    print(i)
  1. Probiere beide Codes aus. Du wirst feststellen, dass beide Codes genau die gleiche Ausgabe haben.
  2. Programmiere sowohl mit einer for- als auch while-Schleife einen Code, der 15 mal den gleichen Text ausgibt. (a)
  3. Beantworte die Fragen unten.

Aufgabe 2: break und continue

1
2
3
4
5
6
i = 1
while i < 8:
    if i == 5:
        break
    i += 1
print(i)
  1. Überlege, welchen Wert i haben könnte. Kommentiere anschließend den print()-Befehl aus und teste. Wie würdest du das erklären?
  2. Schreibe ein Skript, das i bis 20 iterieren würde, aber bei 14 aufhört. (a)
  3. Recherchiere, was der Befehl “continue” bei while-Schleifen bewirkt. Nutze ihn, um in einer while-Schleife alle Zahlen von 1 bis 100 zu überspringen, die durch 3 teilbar sind. Die Ausgabe soll also etwa so aussehen: 1,2,4,5,7,8,10,… (a)
  4. While-Schleifen können auch für den Fall, dass die Prüfbedingung nicht mehr stimmt, etwas ganz bestimmtes ausführen, bevor es einfach weitergeht. Prüfe den Code unten. Stimmt die Aussage?
1
2
3
4
5
6
7
8
k = 50
while k >= 0:
  print(k)
  k -= 1
else:
  print("k ist jetzt negativ!") #dieser else-Block gehört noch zur while-Schleife!

print("Du hast die Schleife offiziell verlassen.") #der Befehl kommt nach dem while-Block

Aufgabe 3: Eingabevalidierung

Schreibe ein Skript, dass folgende Kriterien erfüllt (a):

  • Nimmt Eingaben des Nutzers per input() an.
  • Prüfe die Eingaben per while-Schleife.
  • Solange die Bedingung nicht erfüllt ist, wird der Nutzer oder die Nutzerin erneut gefragt.
Tipp anzeigen
1
2
3
4
eingabe = input("Frage an Nutzer:in")

while eingabe != "prüftext": #prüft die Variable eingabe mit Vergleichsoperatoren
    #dein Code hier. Wichtig: Denke daran, erneut nach input() zu fragen!

Aufgabe 4: Zeitbasierte Schleifen

Insbesondere bei sich dynamisch und außerhalb des Loops ändernden Werten, bieten sich while-Loops an. Mit einer for-Schleife kann man bspw. nicht bzw. nicht sinnvoll mit Zeitpunkten oder Zeiträume umgehen.

  1. Analysiere den Code unten und stelle eine Vermutung auf, bevor du ihn ausführst.
  2. Führe den Code aus und beobachte. Was passiert? Schreibe Kommentare über die Blöcke oder hinter die Zeilen. (a)
  3. Ändere den Code so, dass er 20 Sekunden lang alle 3 Sekunden “tik” in der Konsole ausgibt.
  4. Schreibe verschiedene Codes mit while-Schleifen:
    1. Es wird abwechselnd “tik” und “tak” mit zeitlicher Verzögerung ausgegeben. (a)
    2. Eine Geschichte wird mit Pausen erzählt. Zwischendurch wird der Nutzer um eine Eingabe gebeten. (a)

Beispielcode:

1
2
3
4
5
6
7
8
import time #importiere Modul time
ende = time.time()+20 # jetzt = time.time(), +20 jetzt+20

while time.time() < ende:
    print("..tik..")
    time.sleep(1) # time.sleep(x) Warte x Sekunden
    print("..tak..")
    time.sleep(1)

Aufgabe 5 (extra): Komplexe Fallunterscheidungen

Löse Aufgabe 3 mit if-else- und elif- Bedingungen mit Fallunterscheidungen. Überlege dir dazu ein sinnvolles Beispiel. (a, freiwillig)


Flask-Anwendung (Bonus)

Voraussetzung für diese Aufgabe

Du solltest bereits Flask – 01 Erste Schritte, Flask – 02 Jinja Templating Grundlagen und Flask – 03 Jinja Schleifen und Listen durchgearbeitet haben. Wenn nicht, überspringe diese Bonus-Aufgabe zunächst.

Bonus: Formular mit Eingabevalidierung

Erstelle eine Flask-App mit einem Formular, das Eingaben validiert – ähnlich wie in Aufgabe 3!

Anforderungen:

  1. Erstelle eine Route /registrierung mit GET und POST
  2. Zeige ein Formular mit folgenden Feldern:
    • Benutzername (mindestens 3 Zeichen)
    • Alter (muss zwischen 10 und 100 sein)
    • E-Mail (muss @ enthalten)
  3. Validiere die Eingaben mit if-Bedingungen
  4. Bei Fehlern:
    • Zeige eine Fehlerliste im Template
    • Zeige das Formular erneut an (wie while-Schleife!)
  5. Bei Erfolg:
    • Zeige eine Erfolgsmeldung

Tipp: In Flask ersetzt das wiederholte Anzeigen des Formulars mit Fehlermeldungen die while-Schleife!

Lösung zeigen

app.py:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
from flask import Flask, render_template, request

app = Flask(__name__)

def validiere_benutzername(name: str) -> tuple[bool, str]:
    """Validiert den Benutzernamen. Gibt (ist_gültig, Fehlermeldung) zurück."""
    if not name:
        return (False, "Benutzername darf nicht leer sein")
    if len(name) < 3:
        return (False, "Benutzername muss mindestens 3 Zeichen haben")
    if not name.isalnum():
        return (False, "Benutzername darf nur Buchstaben und Zahlen enthalten")
    return (True, "")

def validiere_alter(alter_str: str) -> tuple[bool, str]:
    """Validiert das Alter. Gibt (ist_gültig, Fehlermeldung) zurück."""
    if not alter_str:
        return (False, "Alter darf nicht leer sein")

    try:
        alter = int(alter_str)
    except ValueError:
        return (False, "Alter muss eine Zahl sein")

    if alter < 10 or alter > 100:
        return (False, "Alter muss zwischen 10 und 100 liegen")

    return (True, "")

def validiere_email(email: str) -> tuple[bool, str]:
    """Validiert die E-Mail-Adresse. Gibt (ist_gültig, Fehlermeldung) zurück."""
    if not email:
        return (False, "E-Mail darf nicht leer sein")
    if "@" not in email or "." not in email:
        return (False, "E-Mail muss @ und . enthalten")
    if email.count("@") != 1:
        return (False, "E-Mail darf nur ein @ enthalten")
    return (True, "")

@app.route("/")
def home():
    return render_template("home.html")

@app.route("/registrierung", methods=['GET', 'POST'])
def registrierung():
    if request.method == 'POST':
        # Formulardaten holen
        benutzername = request.form.get('benutzername', '')
        alter_str = request.form.get('alter', '')
        email = request.form.get('email', '')

        # Fehler sammeln (wie in einer while-Schleife Bedingungen prüfen!)
        fehler = []

        # Validierung durchführen
        gueltig, fehlertext = validiere_benutzername(benutzername)
        if not gueltig:
            fehler.append(fehlertext)

        gueltig, fehlertext = validiere_alter(alter_str)
        if not gueltig:
            fehler.append(fehlertext)

        gueltig, fehlertext = validiere_email(email)
        if not gueltig:
            fehler.append(fehlertext)

        # Wenn Fehler existieren, zeige Formular erneut (wie while-Schleife!)
        if fehler:
            return render_template("registrierung_formular.html",
                                   fehler=fehler,
                                   benutzername=benutzername,
                                   alter=alter_str,
                                   email=email)

        # Erfolg! Keine Fehler, zeige Erfolgsmeldung
        return render_template("registrierung_erfolg.html",
                               benutzername=benutzername)

    # GET-Request: Zeige leeres Formular
    return render_template("registrierung_formular.html")

if __name__ == "__main__":
    app.run(debug=True)

templates/registrierung_formular.html:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <title>Registrierung</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 500px;
            margin: 50px auto;
            padding: 20px;
            background: #f0f0f0;
        }
        .container {
            background: white;
            padding: 30px;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        h1 {
            color: #333;
            text-align: center;
        }
        .fehler {
            background: #ffebee;
            color: #c62828;
            padding: 15px;
            border-radius: 5px;
            margin-bottom: 20px;
            border-left: 4px solid #c62828;
        }
        .fehler h3 {
            margin-top: 0;
        }
        label {
            display: block;
            margin-top: 15px;
            font-weight: bold;
            color: #555;
        }
        input {
            width: 100%;
            padding: 10px;
            margin-top: 5px;
            border: 2px solid #ddd;
            border-radius: 5px;
            font-size: 16px;
        }
        input:focus {
            outline: none;
            border-color: #4caf50;
        }
        button {
            width: 100%;
            padding: 12px;
            margin-top: 20px;
            background: #4caf50;
            color: white;
            border: none;
            border-radius: 5px;
            font-size: 16px;
            cursor: pointer;
            font-weight: bold;
        }
        button:hover {
            background: #45a049;
        }
        .info {
            background: #e3f2fd;
            padding: 10px;
            border-radius: 5px;
            margin-top: 20px;
            font-size: 14px;
            color: #1976d2;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Registrierung</h1>

        {% if fehler %}
        <div class="fehler">
            <h3>Bitte korrigiere folgende Fehler:</h3>
            <ul>
            {% for fehler_text in fehler %}
                <li>{{ fehler_text }}</li>
            {% endfor %}
            </ul>
        </div>
        {% endif %}

        <form method="POST">
            <label>Benutzername:</label>
            <input type="text" name="benutzername"
                   value="{{ benutzername if benutzername else '' }}"
                   placeholder="Mindestens 3 Zeichen">

            <label>Alter:</label>
            <input type="number" name="alter"
                   value="{{ alter if alter else '' }}"
                   placeholder="Zwischen 10 und 100">

            <label>E-Mail:</label>
            <input type="email" name="email"
                   value="{{ email if email else '' }}"
                   placeholder="deine@email.de">

            <button type="submit">Registrieren</button>
        </form>

        <div class="info">
            <strong>Tipp:</strong> Dieses Formular funktioniert wie eine while-Schleife!
            Es wird solange neu angezeigt, bis alle Eingaben korrekt sind.
        </div>
    </div>
</body>
</html>

templates/registrierung_erfolg.html:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <title>Registrierung erfolgreich</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 500px;
            margin: 50px auto;
            padding: 20px;
            background: #f0f0f0;
        }
        .container {
            background: white;
            padding: 30px;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            text-align: center;
        }
        h1 {
            color: #4caf50;
        }
        .erfolg {
            background: #e8f5e9;
            color: #2e7d32;
            padding: 20px;
            border-radius: 5px;
            margin: 20px 0;
            border-left: 4px solid #4caf50;
        }
        .check {
            font-size: 48px;
            color: #4caf50;
        }
        a {
            display: inline-block;
            margin-top: 20px;
            padding: 10px 20px;
            background: #2196f3;
            color: white;
            text-decoration: none;
            border-radius: 5px;
        }
        a:hover {
            background: #1976d2;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="check">OK</div>
        <h1>Registrierung erfolgreich!</h1>

        <div class="erfolg">
            <p><strong>Willkommen, {{ benutzername }}!</strong></p>
            <p>Deine Registrierung war erfolgreich. Alle Eingaben wurden validiert!</p>
        </div>

        <a href="/registrierung">← Zurück zur Registrierung</a>
    </div>
</body>
</html>

So funktioniert es wie eine while-Schleife:

  1. Erste Anzeige: Formular wird angezeigt (wie while fehler == 1:)
  2. Validierung: Eingaben werden geprüft
  3. Fehlerfall: Formular wird MIT Fehlermeldungen erneut angezeigt (Schleife wiederholt sich)
  4. Erfolgsfall: Erfolgsseite wird angezeigt (Schleife wird verlassen)
Zuletzt aktualisiert am