5. Kontrollstrukturen

In diesem Kapitel geht es um die Strukturen, namentlich Verzweigungen, Schleifen und Funktionen, mit denen man den Ablauf eines Python-Skripts steuern kann.
 

Verzweigung

Die if-Verzweigung funktioniert wie aus anderen Sprachen gewohnt, mit kleinen sysntaktischen Differenzen.

Beispiel:
>>> if x < y:
...     print "x is smaller"
...     x = x+1
... elif x == y:
...     print "x equals y"
... else:
...     print "y is smaller"
...     y = y+1

Hierbei entspricht das 'elif' dem 'else if' und hilft, übermäßige Einrückungen zu vermeiden. Die Konstruktion aus if .. elif .. else ersetzt die aus anderen Sprachen bekannte switch-Anweisung.
 

Schleifen

Python besitzt zwei Schleifenarten, die while-Schleife sowie die for-Schleife.
 

While

Die while-Schleife arbeitet wie gewohnt, nämlich so lange, bis die Bedingung im Schleifenkopf false ist.

Beispiel:
>>> while (y != 0):
...     print x, y
...     x, y = y, x%y
 

For

Die for-Schleife unterscheidet sich etwas von den aus C und Pascal-Abkömmlingen gewohnten Varianten. Sie iteriert nämlich über beliebige Sequenzen, beispielsweise über alle Elemente einer Liste oder auch über einen Zahlenbereich.
Bei veränderbaren Sequenzen (wie Listen und Dictionaries) muß man natürlich darauf achten, den Ablauf nicht im Schleifenrumpf durcheinanderzubringen. Möchte man daher sowohl über eine solche Sequenz sowohl iterieren als auch deren Inhalt in der Schleife ändern, wird empfohlen, im Schleifenkopf auf eine Kopie des Objekts zurückzugreifen.

Beispiel:
>>> list = ["one", "two", "three"]
>>> for elem in list:
...     print elem, len(elem)
...
one 3
two 3
three 5
>>> for elem in list[:]:       # Liste kopieren
...     list.append(len(elem)) # Liste kann geändert werden
...
>>> list
['one', 'two', 'three', 3, 3, 5]

Um über Zahlbereiche zu iterieren, greift man am besten auf die eingebaute Funktion range(start, end, inc) zurück, die eine Zahlensequenz von start bis end-1, wobei der Unterschied zwischen den Zahlen immer inc beträgt, zurückliefert.
Start und inc müssen nicht angegeben werden, ihre Standardwerte sind 0 bzw. 1.
>>> for i in range(11):  # entspricht range(0, 11, 1)
...     print i, "squared equals" i**2
...
0 squared equals 0
1 squared equals 1
2 squared equals 4
3 squared equals 9
4 squared equals 16
5 squared equals 25
6 squared equals 36
7 squared equals 49
8 squared equals 64
9 squared equals 81
10 squared equals 100
 

Break/Continue

Wie in C gibt es auch in Python break und continue. Break bricht aus der umschließenden Schleife aus, continue springt direkt zum nächsten Durchlauf.
Deshalb können Schleifen auch einen else-Zweig haben, der nur betreten wird, wenn die Schleife normal (also nicht durch ein break) beendet wurde.

Beispiel:
>>> while x < y:
...     x, y = x+1, y-1
...     if (x == y):
...         print "x = y =", x
...         break;
... else:
...     print "x = y+1 =", x
 

Funktionen

Funktionsdefinitionen werden in Python über das Schlüsselwort def eingeleitet, dann kommt der Funktionsname und in runden Klammern die erwarteten Parameter. Jede Funktion liefert standardmäßig None zurück, man kann aber natürlich im Funktionsrumpf selbst einen Rückgabewert angeben.
Die Funktion erhält beim Aufruf die Referenzen der Aktualparameter, sodaß sich Änderungen nach außen auswirken können.

Beispiel (Fakultätsfunktion):
>>> def faculty(n):        # neue Funktion namens "faculty" mit
                           # einem Parameter wird eingeführt
...     fact = 1           # späterer Rückgabewert
...     for i in range(2, n+1):
...         fact = fact*i  # Berechnung für Werte größer 1
...     return fact
...
>>> faculty(3)             # Aufruf der Funktion
6                          # Rückgabewert wird ausgegeben

Funktionen sind selbst Objekte und können anderen Variablen zugewiesen werden:
>>> fac = faculty  # fac ist ein Alias für faculty
>>> fac(5)         # entspricht faculty(5)
120

Standardparameter
Overloading gibt es in Python nicht, aber es gibt ähnlich wie in C die Möglichkeit, für beliebige Funktionsparameter Standardwerte zur Verfügung zu stellen. Beim Aufruf muß ein solcher Parameter nicht unbedingt angegeben werden.
Werden Standardparameter verwendet, müssen sie rechts von allen anderen Parametern stehen

Beispiel: (power-Funktion)
>>> def pow(base, exp=2):
...     result = 1
...     for i in range(0, exp):
...         result = result * base
...     return result
...
>>> pow(3,3)
27
>>> pow(5)
25

Wenn man beim Aufruf nicht alle verfügbaren Standardparameter befallen möchte, muß man besondere Regeln beachten. Zuerst kann man, von links beginnend, nach der Reihe Parameter befüllen, ohne deren Namen angeben zu müssen. Ab dem ersten ausgelassenen Wert muß man die restlichen Parameter zusätzlich mit deren Namen qualifizieren. Dabei dürfen natürlich keine Parameter doppelt befüllt werden.

Beispiel:
>>> def someFunc(arg1, arg2, arg3="three", arg4="four", arg5="five"):  # gibt einfach die Parameterwerte aus
...     print "arg1:", arg1, "arg2:", arg2, "arg3:", arg3, "arg4:", arg4, "arg5:", arg5
...
>>> someFunc(3)
Traceback (innermost last):
  File "<pyshell#78>", line 1, in ?
    someFunc(3)
TypeError: not enough arguments; expected 2, got 1
# schlägt fehl, weil 2 Parameter befüllt werden müssen

>>> someFunc(2 ,4)
arg1: 2 arg2: 4 arg3: three arg4: four arg5: five
# die beiden ersten Argumente sind wie verlangt befüllt
# die Standardargumente haben ihre Defaultwerte

>>> someFunc(arg1=2, arg2=4, arg3="abc", "four", "five")
SyntaxError: non-keyword arg after keyword arg
# wenn man einmal mit der Namensqualifikation beginnt,
# muß man sie auch für die restlichen Elemente beibehalten

>>> someFunc(2, arg2=5, arg4=4)
arg1: 2 arg2: 5 arg3: three arg4: 4 arg5: five
# die normalen + 1 Standardargument sind befüllt

>>> someFunc(1, 2, 3, 4)
arg1: 1 arg2: 2 arg3: 3 arg4: 4 arg5: five
# der Interpreter setzt von links beginnend einfach ein
# -> nur arg5 wird nicht überschrieben

>>> someFunc(1, 2, 3, arg5=4)
arg1: 1 arg2: 2 arg3: 3 arg4: four arg5: 4
# arg 4  wird ausgelassen
# daher muß arg5 namentlich angegeben werden

>>> someFunc(1, 2, 3, arg3=3)
Traceback (innermost last):
  File "<pyshell#86>", line 1, in ?
    someFunc(1, 2, 3, arg3=3)
TypeError: keyword parameter redefined: arg3
# arg3 wurde aufgrund der Reihenfolge schon befüllt
# die zusätzliche namentliche Belegung ist also unzulässig
 
 

Datentypen