Schleifen#

(Klicken Sie hier für die englische Version dieser Seite)

Gängige Schleifen gibt es in Python ebenfalls mit den aus anderen Programmiersprachen bekannten Keywords for und while.

Hier unterscheidet Python sich jedoch syntaktisch von den C-ähnlichen Programmiersprachen.

For-Schleife#

In C wird ein Codeblock in einer for-Schleife ausgeführt solange eine Bedingung erfüllt ist. Bei Algorithmen werden üblicherweise einbuchstabige Namen für die Zählvariablen gewählt, die meist einfach inkrementiert oder dekrementiert werden. Größtenteils werden i und j verwendet.

Python geht bei Schleifen anders vor: Die Anzahl der Wiederholungen einer Schleife basieren nicht auf Formeln und Bedingungen zu Zählvariablen, sondern übergibt man ein “iterable” Objekt. Das ist ein Objekt, welches Werte zurück gibt, die beispielsweise als Indizes verwendet werden können.

In C würde man eine For-Schleife startend bei 0 mit Schrittweite 1 so erstellen:

for (int i = 0; i < wert_für_i_welcher_nicht_mehr_dazugehören_soll; i++) {
    <Codeblock>
}

Die einzelnen Werte für i werden wie folgt berechnet. Man fängt bei i = 0 an und inkrementiert bis der Wert erreicht ist, bei dem die Bedingung nicht mehrerfüllt ist.

In Python übergibt man hingegen die Werte 0 bis zum Grenzwert in Form einem iterable Object, wie etwa einer Liste.

Folgendes Beispiel in C

for (int i = 0; i < 5; i++) {
	<Codeblock>
}

würde man in Python folgendermaßen erstellen:

for i in [0, 1, 2, 3, 4]:
	<Codeblock>

Das Keyword in sagt hier, dass der jeweils aktuelle Wert der List [0, 1, 2, 3, 4] als i anzusprechen sei.

Die angenehmste Methode ist die range() Funktion#

Man möchte natürlich nicht jeden Index einzeln schreiben, deshalb gibt es die sogenannte range()-Funktion. Diese erhält unter anderem zwei Zahlen als Parameter. Die erste ist der Startwert. Die zweite ist die erste Zahl, welche nicht mehr dazugehört - wie beim Slicing.

Standardmäßig beträgt die Schrittweite 1. Man kann jedoch auch als dritten Parameter die Schrittweite angeben. Die kann sowohl positiv als auch negativ sein, bei negativen Schrittweiten muss man jedoch darauf aufpassen, dass das erste Argument größer ist als das zweite Argument.

range(0, n)

gibt also eine Datenstruktur mit den Zahlen 0 bis n-1 zurück. Technisch gesehen ist es was anderes als eine Liste von 0 bis n-1. Man kann es aber mit list(range(0, n)) zu eben einer Liste von 0 bis n-1 casten. Für die For-Schleife ist dieser Cast jedoch nicht nötig.

Eine praktischere Variante des oberen Python-Codes wäre also

for i in range(0, 5):
	<Codeblock, ausgeführt für i=0, i=1, ..., i=4>

Sofern der Startwert 0 ist, kann dieser auch weggelassen werden. In diesem Fall wird der erste und einzige Parameter als obere Schranke interpretiert

liste = [31, 12, 63, 44, 35]
for i in range(len(liste)):
	<Codeblock>

Hiermit wird der Codeblock für alle erlaubten Indizes der Liste liste einmal ausgeführt, nämlich von 0 bis len(liste)-1.

Möchte man nun eine absteigende For-Schleife von 10 bis inklusive 3 mit Schrittweite 1, dann kann man dies so machen:

for i in range(10, 2, -1):
    <Mache etwas mit i>

Die For-Schleife startet bei 10 und geht bis exklusiv 2. Da wir die Schleife bis inklusiv 3 haben wollen, geben wir den ersten Wert an, der nicht mehr dazu gehören soll, also die Zahl 2. Die -1 als drittes Argument gibt an, dass die Schrittweite -1 betragen soll.

Alternativ kann man die range von 3 bis inklusiv 10 (bis exklusiv 11) nehmen und diese mit der reversed() Funktion umdrehen:

for i in reversed(range(3, 11)):
    <Mache etwas mit i>

Iterieren durch andere iterierbare Objekte#

Jetzt kommt man zu dem sehr angenehmen Teil von Python, wenn es darum geht, über eine Liste zu iterieren. Beim Iterieren möchte man meistens den Codeblock für jeden Eintrag in einer Liste ausführen. Anstatt dabei jetzt mit Indizes zu arbeiten, kann man auch direkt durch die Liste iterieren, ganz intuitiv.

Aussehen würde es so:

for person in personen:
    <Mache etwas mit person>

Man kann es sich so vorstellen würde wie Schleifen in C, dann wäre person ein Shortcut für personen[i], wobei i der jeweils aktuelle Index des Objekts wäre.

Wenn man aber explizit mit Indizes arbeiten möchte, lässt Python dies zu. Das würde dann so aussehen:

for i in range(len(personen)):
    <Mache etwas mit personen[i]>

Da in range(len(personen)), die Werte von 0 bis len(personen)-1 vertreten sind, werden alle Indizes der Liste personen abgedeckt.

Durch iterierbare Objekte iterarieren mit Zugriff auf Indizes#

Möchte man über ein iterierbaren Element iterieren wie z.B.

for person in personen:
    <Mache etwas mit person>

dann hat man keinen Zugriff auf den aktuellen Index. Falls man denoch sowohl Zugriff auf den Index als auch auf das Element haben möchte, kann die Funktion enumerate() genutzt werden. Diese Funktion wäre die angenehmste Option wenn man sowohl den Index als auch das Element haben möchte.

Die enumerate() Funktion nimmt das iterierbare Objekt als Parameter und gibt ein iterarierbaren Objekt zurück, wo für jeden Eintrag, das jeweils erste Element der Index ist und das zweite Element das Element aus dem iterierbaren Objekt ist. Wenn man

for index, element in enumerate(elemente):
	<Mach etwas mit index und element>

nutzt, so hat man Zugriff auf sowohl den Index als auch das Element in jeder Iteration.

While-Schleife#

Hier wird ein Codeblock so oft ausgeführt, bis die Bedingung nicht mehr gilt.

while bedingung:
	<Codeblock>

Beispiel:

while n > 0:
	n -= 1

Man beachte, dass es in C zwei Arten von While-Schleifen gibt. Die normale While-Schleife

while(bedingung) {
	<Codeblock>
}

und die Do-While-Schleife

do {
	<Codeblock>
} 
while(bedingung)

Bei letzterem wird die Bedingung erst nach Ausführen des Codeblocks überprüft. Diese Option gibt es nicht in Python. Möchte man dieses Verhalten in Python imitieren, so kann man zum Beispiel mit einer Endlosschleife und bedingtem break arbeiten.

Das Keyword break beendet manuell die aktuelle Schleife. Bei einer Endlosschleife ist break die einzige Möglichkeit, die Schleife zu beenden.

while True: # Endlosschleife
	<Codeblock>
	if not bedingung:
		break

Do-While-Schleifen werden eher seltener benutzt, deshalb wird man ihr Fehlen in Python eher weniger spüren, vor allem, da es einen Workaround gibt.

Aufgabe#

Jemand hat ein Programm in C geschrieben und offenbar ist etwas schief gelaufen. Die Einrückung wurde gelöscht. Ihre Aufgabe ist, das Programm in Python umzuschreiben, damit man einen Performancevergleich der beiden Programme durchführen kann. Dass die Einrückung verschwunden ist, macht Ihr Leben sicherlich nicht einfacher.

int result = 0;
for (int i = 0; i < 3; i++) {
result = result + i * 3;
for (int j = 3; j > 1; j--) {
result -= j;    
int k = 5;
while (k > i) {
result += j;
k = k / 2;
}
}
}    
printf("%d", result);

Jemand hat für Sie schon Vorarbeit geleistet und hat den Großteil des Programms bereits in Python geschrieben. Es fehlen nur noch die Schleifen, dort steht <Loop>. Die Einrückung für die hinzuzufügenden Schleifen wurde ebenfalls gelöscht. Die Person hat den Großteil des Programms auskommentiert. Ihre Aufgabe ist es nun, das Auskommentieren rückgängig zu machen und die passenden Schleifen an die korrekten Stellen einzufügen. Für das Rückgängigmachen des Auskommentierens, können Sie die triple-quotes(”””) entfernen. Die gewünschte Funktionsweise der Schleifen ist im obigen C-Code ersichtlich.

# Ersetzen Sie "<Loop>" durch die jeweils korrekten Schleifen.
# Achten Sie auf korrekte Einrückung.
result = 0
"""
<Loop>
result = result + i * 3 
<Loop>
result -= j
k = 5
<Loop>
result += j
k = k // 2
"""
print(result)
0