Schlaufen

Block 7

Wenn du die Vektoraufgabe für verschiedene Paare von Vektoren ausführen möchtest, musst du dein Programm im Moment mehrmals starten. Auch wenn der Spieler beim Quiz einen weiteren Versuch möchte, muss er das Programm neu starten. Du wirst oft ähnliche Situationen antreffen, in denen du Code n-mal ausführen möchtest. Die Lösung für solche Situationen sind Schlaufen.

while

a = 2 while a < 500: print(a) a *= a

Mit while beginnst du einen Code-Block, der solange wiederholt wird, wie die nachfolgende Bedingung True ist. In unserem Beispiel ist die Bedingung, dass a kleiner ist als 500. Solange das gilt, wird a ausgegeben und dann quadriert.

Hinweis: Das Beispiel oben verwendet eine besondere Syntax um a zu verändern. Da es häufig vorkommt, dass du eine Variable abhängig von ihrem aktuellen Wert verändern möchtest, gibt es dafür eine Kurzschreibweise. a *= a ist die Kurzform von a = a*a. Analog funktionieren +=, -= und /=.

Es ist wichtig, dass du das erste Schlaufen-Beispiel verstehst. Nimm dir deshalb ein Blatt Papier und vervollständige folgende Tabelle für die gesamte Programmausführung.

code aKommentar
a = 2 2
while a < 500: 2True
print(a) 2Ausgabe: 2
a *= a 4
while a < 500: 4True
print(a) ...

Wir wollen nun mit while das Mondlandungsquiz erweitern. Dein Quiz sei in der Funktion frage() definiert. Diese Funktion gibt True zurück wenn die Frage richtig beantwortet wurde, sonst False. Ist die Antwort falsch, so wollen wir dem Spieler einen weiteren Versuch anbieten.

def frage(): ans = input("Wann war der erste Mensch \ auf dem Mond? (YYYY-mm-dd) ") return ans == '1969-07-20' again = True while again: result = frage() print(result) if not result: ans = input("Weiterer Versuch? (J,n) ") if (ans.lower() == "n"): again = False else: again = False

In diesem Fall ist die Bedingung die Variable again, die zu Beginn auf True gesetzt wird. Im While-Block wird die Variable dann auf False gesetzt, wenn entweder die Frage richtig beantwortet wurde oder der Spieler aufgibt.

Wenn du dir nicht sicher bist, was bei der Ausführung passiert, erstelle auch hier eine Tabelle mit den ausgeführten Befehlen. Manchmal ist auch ein Fluss-Diagram sehr hilfreich.

Aufgabe 1

Erstelle eine Programm, dass eine Liste mit Namen zusammenstellt. Das Programm soll dich nach einem Namen fragen und diesen zu einer Liste hinzufügen. Du sollst solange Namen eingeben können, wie du nicht einen leeren String eingibst. Überlege dir die Struktur des Programms zuerst auf Papier.

Lösung anzeigen

namen = [] neu = "bla" while neu != "": neu = input("neuer Name: ") namen.append(neu) print(namen[0:-1])

Aufgabe 2

Verwende while und folgende Regeln um den ggT von zwei Integer-Zahlen a und b zu berechnen:

Hinweise: Du brauchst hier %. % ist der Operator für die Modulo-Division. a % b gibt dir also den Rest bei der Division von a durch b.

Lösung anzeigen

import sys try: a = int(input("a: ")) b = int(input("b: ")) except ValueError: sys.exit(1) while (b != 0): tmp = a a = b b = tmp % b print("ggT:", a)

break

Manchmal kommt es vor, dass du eine Schlaufe vorzeitig beenden möchtest. Dazu kannst du break verwenden.

a = 2 while a < 500: print(a) a *= a if (a == 16): break

Aufgabe 3

Vereinfache dein Programm um die Namen einzulesen, in dem du while True: verwendest und statt dessen die Schlaufe mit break beendest.
Achtung: Wenn du break vergisst, beendet dein Programm nie mehr.

Lösung anzeigen

namen = [] while True: neu = input("neuer Name: ") if (neu == ""): break namen.append(neu) print(namen)

for

Neben der while-Schleife kennt Python auch die for-Schleife. Damit kannst du einen Code-Block für jedes Element einer Liste (oder eines Listen-ähnlichen Objekts) ausführen lassen. Aus

print("Ich esse gerne Birnen") print("Ich esse gerne Orangen") print("Ich esse gerne Pflaumen") print("Ich esse gerne Bananen")

wird damit

liste = ["Birnen", "Orangen", "Pflaumen", "Bananen")] for frucht in liste: print("Ich esse gerne", frucht)

Das besonders nützlich, wenn du diese Früchte später nicht mehr essen möchtest. In dem Fall musst du nur ein Mal nicht einfügen, und nicht vier Mal.

Auch hier ist es sinnvoll, wenn du die Programmausführung mit einer Tabelle oder einem Flussdiagramm veranschaulichst:

code fruchtAusgabe
liste = [...] -
for frucht [...]Birnen
print([...]) BirnenIch esse gerne Birnen
for frucht [...]...

Aufgabe 4

Ergänze dein Namen-Programm mit einer for-Schlaufe, die alle eingelesenen Namen begrüsst.

Lösung anzeigen

namen = [] while True: neu = input("neuer Name: ") if (neu == ""): break namen.append(neu) print() for name in namen: print("hallo", name)

Aufgabe 5

Wie wir gesehen haben, ist auch ein String ein Listen-artiges Objekt. Du kannst deshalb mit einer for-Schleife auch auf die einzelnen Buchstaben eines Strings zugreifen. Schreibe ein Programm, dass ein Wort einliest und dann Buchstabe für Buchstabe wieder ausgibt.

Lösung anzeigen

wort = input("Was soll ich buchstabieren? ") for buchstabe in wort: print(buchstabe)

for mit Zahlen

Oft soll Code auch einfach für eine gewisse Anzahl von Wiederholungen ausgeführt werden.

print("ROMANI ITE DOMUM!") print("ROMANI ITE DOMUM!") print("ROMANI ITE DOMUM!") print("ROMANI ITE DOMUM!") print("ROMANI ITE DOMUM!") print("ROMANI ITE DOMUM!") print("ROMANI ITE DOMUM!") print("ROMANI ITE DOMUM!") print("ROMANI ITE DOMUM!") print("ROMANI ITE DOMUM!")

Mit einer for-Schleife lässt sich das einfacher erreichen. Dafür brauchen wir eine Liste mit 10 Einträgen, was die Einträge genau sind, ist dabei egal. Wir können zum Beispiel eine Liste mit 10 mal dem Wert 0 verwenden:

for i in [0]*10: print("ROMANI ITE DOMUM!")

Wie du siehst, verwenden wir die Variable i in der Schlaufe nirgends. Das ist völlig ok. Es gibt aber auch immer wieder Fälle in denen du die Zahlen in den Schlaufen verwenden möchtest. So können wir unsere Ausgabe zum Beispiel nummerieren.

for i in [1,2,3,4,5,6,7,8,9,10]: print(i, "ROMANI ITE DOMUM!")

in range(...)

Noch etwas eleganter, wird es wenn du die nötige Liste mit range erzeugst.

for i in range(1, 11): print(i, "ROMANI ITE DOMUM!")

Beachte, dass wir hier range ohne list verwendet haben. Das funktioniert, weil wir hier die Elemente einzeln und nicht als ganze Liste brauchen.

Aufgabe 6

Verwende for um:

Lösung anzeigen

# auf 3 zählen for i in range(1,4): print(i) # von 10 rückwärts zählen for j in range(10, 0, -1): print(" ", j) # 6-er Reihe for i in range(1, 11): print(6*i) # oder for i in range(0, 61, 6): print(i)

Aufgabe 7

Schreibe ein Programm, das folgende Ausgabe erzeugt. Du musst dafür zwei Schlaufen verschachteln.

0 1 1 2 2 1 3 3 2 1

Lösung anzeigen

for i in range(4): print(i) for j in range(i, 0, -1): print(" ", j)

Aufgabe 8

Implementiere ein Programm, das n einliest und dann alle ganzen Zahlen von 1 bis n addiert. Dein Programm soll das Ergebnis auf vier Arten lösen:

Lösung anzeigen

import sys try: max = int(input("N = ")) except ValueError: sys.exit(1) total_for = 0 total_while = 0 total_sum = 0 total_math = 0 for i in range(max+1): total_for += i n = max while n > 0: total_while += n n -= 1 total_sum = sum(range(max+1)) total_math = max*(max+1)/2 print(total_for, " = ", total_while, " = ", total_sum, " = ", total_math)

Du siehst, oft gibt es mehr als eine Lösung für das gleiche Problem. Meist sind sie unterschiedlich gut geeignet. Es lohnt sich deshalb zuerst zu überlegen und dann zu tippen.

Aufgabe 9

Berechne die Quadrate folgender Zahlen.

(Ich hoffe du weist noch wie du mit range die 2. und 3. Liste generieren kannst.)

Lösung anzeigen

liste = [] liste.extend([1, 3, 5, 7, 11, 13, 17, 19]) liste.extend(range(2,21,2)) liste.extend(range(-1,-10,-1)) for i in liste: print(i*i)

arrays statt for-Schleifen

In der Aufgabe oben haben wir eine for-Schlaufe verwendet um auf mehreren Werten mathematische Operationen auszuführen. Das ist die traditionelle Methode dieses Problem zu lösen. In Pylab kannst du solche Aufgaben oft eleganter mit Arrays lösen:

from pylab import * liste = array([1, 3, 5, 7, 11, 13, 17, 19]) print(liste**2)

pdb

Schau dir das Programm vollkommen.py an. Es sollte keinen Befehl enthalten, den du nicht verstehst. Lasse das Programm laufen und schau dir den Output an. Leider scheint etwas nicht zu funktionieren. Wir müssen uns also auf die Suche nach dem Fehler machen.

Um den Fehler zu finden, sollten wir die Entwicklung von number, factor und total verfolgen. Dazu hast du zwei Möglichkeiten. Du kannst jede dieser Variablen an der interessanten Stelle durch einen print-Befehl ausgeben lassen. Das lohnt sich aber nur, wenn du bloss eine Variable verfolgen möchtest (z.B.: values in histogram.py).

Eine elegantere Möglichkeit ist den Python-Debugger pdb zu verwenden. Damit kannst du Schritt für Schritt durch dein Programm gehen und schauen, was wo passiert. Öffne vollkommen.py in Spyder und lass es im Debugger laufen (Der Run > Debug oder [ctrl]+[F5].) Der Output in der Console sieht dann etwa so aus:

-> """ (Pdb)

Die Zeile mit dem Pfeil sagt dir wo in der Datei du bist (am Ende des Doc-Strings). (Pdb) ist der Prompt des Debuggers. Im Prompt kannst du nun deine Anweisung eintippen.

Die möglichen Befehle findest du wenn du help eintippst. Die wichtigsten drei sind n, s und p. Schau nach, was diese Befehle bewirken (z.B. mit h n). Nützlich sind auch noch c und b sowie display. (Du kannst dir auch die Liste auf der Website anschauen.)

Aufgabe 10

Verwende pdb um deine Tabellen von oben (while/for-Einführung) zu kontrollieren. Führt Python die Zeilen in der von dir erwarteten Reihenfolge aus? Haben die Variablen die erwarteten Werte?

Aufgabe 11

Verwende pdb um den Fehler in vollkommen.py zu finden und das Programm zu korrigieren.

Lösung anzeigen

break 20 # Ausführung auf Zeile 20 stoppen continue # Ausführen bis zum nächsten Stop (max-Value: 10) display number # Wert von Number ausgehebn wenn er sich ändert continue # zum nächsten Stop ... # bis number = 6 display total # ist noch auf altem Wert (6) display factor # ist noch auf altem Wert (5) next # total wird zurück gesetzt n # factor wird auf 1 gesetzt [enter] # weiter n ausführen ... # bis klar ist weshalb # erwartet: total = 1+2+3 (-> 6) [ctrl]+[d] # Fehler im Skript korrigieren

Hinweis: Es gibt diverse weitere Arten um pdb zu starten. Wenn du dein Skript mit einer Fehlermerldung abbricht, kannst du es mit ipython --pdb dein-skript.py starten. IPython startet dann den Debugger dort wo der Fehler ausgelöst wird. Ausserdem kannst du den Debugger an einer beliebigen Stelle eines Skripts starten, in dem du dort eine Zeile import pdb; pdb.set_trace() einfügst.

while oder for

Du kannst die meisten Probleme sowohl mit while wie auch mit for lösen. Allerdings ist oft eine der beiden Arten besser geeignet. Diskutiere mit deinem Nachbar, wann welcher Schlaufentyp sinnvoller ist.

Lösung anzeigen

for

while

(Falls ihr noch weitere Situationen gefunden habt, sind wir interessiert diese zu hören.)

Aufgaben zur Vertiefung

Hinweis: Schlaufen sind ein zentrales Hilfsmittel beim Programmieren. Es ist deshalb wichtig, dass du ihre Funktionsweise und Verwendung verstanden hast, bevor du zum nächsten Block wechselst.

Quiz mit Wiederholungen

Erstelle eine weiteres Quiz, das die Frage solange wiederholt, bis du die richtige Antwort eintippst. Wähle die Frage selbst. Eine Rechnungsaufgabe wäre eine gute Option.

Lösung anzeigen

antwort = "0" while (antwort != "42"): antwort = input( """ Was ist der Sinn des Leben, des Universums und des ganzen Rest? """ )

Vektorrechnung wiederholt

Passe deine Lösung für die Vektorrechnungsaufgabe (Vertiefungsaufgabe im Input-Block) so an, dass du mehrmals Vektoren eintippen kannst.

Listen mit Schlaufen

Löse die Aufgaben Zählen und Zürichsee aus dem Listen-Block mit Hilfe von Schlaufen.

Kinderlieder

Schreibe ein Programm, dass den Liedtext für Auf der Mauer, Auf der Lauer oder Laurenzia ausgibt.

Collatz-Problem

Collatz-Problem besagt, dass folgende Regel für jeden Startwert zu 1 führt:

  1. Nimm eine beliebige natürliche Zahl a.
  2. Wiederhole folgendes solange bis du 1 erreichst:
    • Wenn die Zahl durch 2 teilbar ist, setze a = a/2
    • sonst setze a = 3*a + 1

Implementiere ein entsprechendes Programm. Lies einen Startwert ein und schaue wie viele Schritte es braucht um 1 zu erreichen. Lies solange neue Startwerte ein, bis du 0 eingibst.

Hinweise: Um zu bestimmen ob eine Zahl durch eine andere teilbar ist, kannst modulo verwenden.