Unterabschnitte


4. Weitere Kontrollstrukturen

Neben der eben eingeführten while-Anweisung kennt Python die bei anderen Sprachen üblichen Kontrollfluß-Anweisungen - mit einigen Tricks.


4.1 if-Anweisungen

Die vielleicht bekannteste Anweisung ist die if-Anweisung, z.B.:


>>> #  [Code, der 'x' auf irgendeinen Wert setzt...]
>>> if x < 0:
...      x = 0
...      print 'Negative changed to zero'
... elif x == 0:
...      print 'Zero'
... elif x == 1:
...      print 'Single'
... else:
...      print 'More'
...

Es kann keine oder mehrere elif-Teile geben, und der else-Teil ist optional. Das Schlüsselwort `elif' ist eine Kurzschreibweise für ,,else if`` und ist nützlich, um exzessive Einrückungen zu vermeiden. Eine Sequenz der Art if ... elif ... elif ... ist ein Ersatz für switch- oder case-Anweisungen in anderen Sprachen.


4.2 for-Anweisungen

Die for-Anweisung in Python unterscheidet sich ein wenig von dem, was Sie aus C oder Pascal gewohnt sind. Anstatt stets über eine arithmetische Folge von Zahlen zu iterieren (wie in Pascal) oder der Benutzerin die Möglichkeit zu geben, die Schrittweite und Endbedingung der Iteration zu definieren (wie in C), iteriert die for-Anweisung in Python über die Elemente einer Sequenz (z.B. einer Liste oder eines Strings) in der Reihenfolge ihres Auftretens in dieser Sequenz. Beispiel:


>>> # Messe einige Strings:
... a = ['cat', 'window', 'defenestrate']
>>> for x in a:
...     print x, len(x)
...
cat 3
window 6
defenestrate 12

Es ist nicht sicher, die Sequenz zu modifizieren, über die gerade iteriert wird (das kann nur mit veränderlichen Sequenztypen passieren, z.B. Listen). Wenn Sie die Liste modifizieren müssen, über die Sie iterieren, z.B. um die einzelnen Elemente zu kopieren, müssen Sie über eine Kopie iterieren. Mit der Teilbereichs-Notation ist dies sehr bequem:


>>> for x in a[:]: # Erstelle eine Teilbereichs-Kopie der ganzen Liste.
...    if len(x) > 6: a.insert(0, x)
...
>>> a
['defenestrate', 'cat', 'window', 'defenestrate']


4.3 Die range()-Funktion

Falls Sie über eine Sequenz von Zahlen iterieren müssen, kommt die eingebaute Funktion range() sehr gelegen. Sie erzeugt Listen, die arithmetischen Aufzählungen entsprechen, z.B.:


>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Der angegebene Endpunkt ist nie Teil der erzeugten Liste. range(10) erzeugt eine Liste von 10 Werten, exakt die gültigen Indizes für Elemente einer Sequenz der Länge 10. Es ist möglich, den Bereich bei einer anderen Zahl anfangen zu lassen oder eine andere ganzzahlige Schrittweite anzugeben (sogar negativ):


>>> range(5, 10)
[5, 6, 7, 8, 9]
>>> range(0, 10, 3)
[0, 3, 6, 9]
>>> range(-10, -100, -30)
[-10, -40, -70]

Um die Indizes einer Sequenz zu durchlaufen, kombiniere man range() und len() wie folgt:


>>> a = ['Mary', 'had', 'a', 'little', 'lamb']
>>> for i in range(len(a)):
...     print i, a[i]
...
0 Mary
1 had
2 a
3 little
4 lamb


4.4 break- und continue-Anweisungen und else-Klauseln in Schleifen

Die break-Anweisung bricht, wie in C, aus der kleinsten umgebenden for- oder while-Schleife aus.

Die continue-Anweisung, auch aus C geliehen, setzt die Schleife mit der nächsten Iteration fort.

Schleifen-Anweisungen dürfen eine else-Klausel haben. Sie wird ausgeführt, wenn die Schleife vollständig durch die Liste gelaufen ist (mit for) oder wenn die Bedingung falsch wird (mit while), aber nicht, wenn die Schleife durch eine break-Anweisung terminiert wird. Dies wird bei der folgenden Schleife deutlich, die nach Primzahlen sucht:


>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...            print n, 'equals', x, '*', n/x
...            break
...     else:
...          print n, 'is a prime number'
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3


4.5 pass-Anweisungen

Die pass-Anweisung tut nichts. Sie kann benutzt werden, wenn eine Anweisung syntaktisch notwendig ist, ohne daß das Programm wirklich etwas tun muß. Beispiel:


>>> while 1:
...       pass # Aktives Warten auf eine Tastatur-Unterbrechung.
...


4.6 Definition von Funktionen

Wir können eine Funktion schreiben, die die Fibonacci-Folge bis zu einer beliebigen Grenze ausgibt:


>>> def fib(n):    # Gib Fibonacci-Reihe bis n aus.
...     "Print a Fibonacci series up to n"
...     a, b = 0, 1
...     while b < n:
...         print b,
...         a, b = b, a+b
...
>>> # Rufe nun die gerade definierte Funktion auf:
... fib(2000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

Das Schlüsselwort def leitet die Definition einer Funktion ein. Ihm muß der Funktionsname folgen sowie eine Liste von formalen Parametern in runden Klammern sowie ein Doppelpunkt. Die Anweisungen, die den Rumpf der Funktion ausmachen, beginnen in der folgenden Zeile, um einen Tabulator eingerückt. Die erste Anweisung des Rumpfes kann optional ein String-Literal sein. Dieses String-Literal ist der Dokumentations-String der Funktion, auch Docstring genannt. Es gibt Werkzeuge, die Docstrings verwenden, um automatisch gedruckte Dokumentation zu erzeugen oder um die Benutzerin interaktiv im Code stöbern zu lassen. Es ist von Vorteil, Docstrings in Ihrem Code zu verwenden. Versuchen Sie, es sich zur Gewohnheit zu machen!

Die Ausführung einer Funktion führt zu einer neuen Symboltabelle mit den lokalen Variablen dieser Funktion. Genauer: alle Variablenzuweisungen in einer Funktion speichern den Wert in der lokalen Symboltabelle, wohingegen Referenzen auf Variablen erst in der lokalen Symboltabelle gesucht werden, dann in der globalen Symboltabelle und dann in der Tabelle der eingebauten Namen. Daher kann in einer Funktion globalen Variablen nicht direkt ein Wert zugewiesen werden (solange sie nicht in in einer global-Anweisung vorkommen), obwohl sie referenziert werden können.

Die eigentlichen Parameter (Argumente) eines Funktionsaufrufs werden dann in die lokale Symboltabelle der aufrufenden Funktion eingefügt, wenn die Funktion aufgerufen wird. Daher werden die Argumente mit Werte-Semantik übergeben (engl. call by value).4.1Wenn eine Funktion eine andere Funktion aufruft, wird eine neue lokale Symboltabelle für diesen Aufruf erzeugt. 4.2

Eine Funktionsdefinition trägt den Namen der Funktion in die aktuelle Symboltabelle ein. Der Wert des Funktionsnamens hat einen Typ, der vom Interpreter als eine benutzerdefinierte Funktion erkannt wird. Dieser Wert kann einem anderen Namen zugewiesen werden, der dann auch als Funktion verwendet werden kann. Dies kann als allgemeiner Mechanismus zur Umbenennung von Funktionen dienen:


>>> fib
<function object at 10042ed0>
>>> f = fib
>>> f(100)
1 1 2 3 5 8 13 21 34 55 89

Sie könnten einwenden, daß fib keine Funktion, sondern eine Prozedur ist. In Python wie in C sind Prozeduren lediglich Funktionen, die keinen Wert zurück geben. Tatsächlich ist es so, technisch gesehen, daß Prozeduren sehr wohl einen Wert zurück geben, wenn auch einen langweiligen. Dieser Wert heißt None (ein eingebauter Name). Die Ausgabe des Wertes None wird normalerweise vom Interpreter unterdrückt, falls es der einzige Ausgabewert ist. Wenn man wirklich will, kann man ihn dennoch sehen:


>>> print fib(0)
None

Es ist einfach, eine Funktion zu schreiben, die eine Liste von Zahlen der Fibonacci-Folge zurück gibt, anstatt sie direkt auszudrucken:


>>> def fib2(n): # Gib Fibonacci-Reihe bis n aus.
...     "Return a list containing the Fibonacci series up to n"
...     result = []
...     a, b = 0, 1
...     while b < n:
...         result.append(b)    # Siehe unten.
...         a, b = b, a+b
...     return result
...
>>> f100 = fib2(100)    # Rufe sie auf.
>>> f100                # Gib das Ergebnis aus.
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

Dieses Beispiel demonstriert, wie üblich, einige neue Eigenschaften von Python:


4.7 Mehr über die Definition von Funktionen

Es ist auch möglich, Funktionen mit einer variablen Anzahl von Argumenten zu definieren. Es gibt drei Formen, die kombiniert werden können:


4.7.1 Argumente mit Vorgabewerten

Die nützlichste Form besteht darin, einen Vorgabewert für ein oder mehrere Argumente zu spezifizieren.


def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
    while 1:
        ok = raw_input(prompt)
        if ok in ('y', 'ye', 'yes'): return 1
        if ok in ('n', 'no', 'nop', 'nope'): return 0
        retries = retries - 1
        if retries < 0: raise IOError, 'refusenik user'
        print complaint

Diese Funktion kann entweder so aufgerufen werden: ask_ok('Wollen Sie wirklich beenden?') oder so: ask_ok('Ist es OK, die Datei zu überschreiben?', 2).

Die Vorgabewerte werden im definierenden Geltungsbereich zum Zeitpunkt der Funktionsdefinition ausgewertet. So wird z.B.


i = 5
def f(arg = i): print arg
i = 6
f()

den Wert 5 ausgeben.

Wichtiger Hinweis: Ein Vorgabewert wird nur einmal ausgewertet. Das macht dann einen Unterschied, wenn es sich um ein veränderliches Objekt handelt, etwa eine Liste oder ein Dictionary. Die folgende Funktion zum Beispiel sammelt die ihr übergebenen Argumente in aufeinander folgenden Aufrufen:


def f(a, l = []):
    l.append(a)
    return l
print f(1)
print f(2)
print f(3)

Das wird folgendes ausgeben:


[1]
[1, 2]
[1, 2, 3]

Wenn Sie nicht wollen, daß aufeinander folgende Aufrufe sich das veränderliche Objekt teilen, können Sie stattdessen die folgende Funktion verwenden:


def f(a, l = None):
    if l is None:
        l = []
    l.append(a)
    return l


4.7.2 Schlüsselwort-Argumente

Funktionen können auch mit Schlüsselwort-Argumenten in der Form "keyword = value" aufgerufen werden. Diese Funktion zum Beispiel,


def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
    print "-- This parrot wouldn't", action,
    print "if you put", voltage, "Volts through it."
    print "-- Lovely plumage, the", type
    print "-- It's", state, "!"

könnte in allen folgenden Varianten aufgerufen werden:


parrot(1000)
parrot(action = 'VOOOOOM', voltage = 1000000)
parrot('a thousand', state = 'pushing up the daisies')
parrot('a million', 'bereft of life', 'jump')

aber diese Aufrufe wären alle ungültig:


parrot()                     # Notwendiges Argument fehlt.
parrot(voltage=5.0, 'dead')  # Schluesselwort-Argument folgt Schluesselwort.
parrot(110, voltage=220)     # Doppelter Wert fuer ein Argument.
parrot(actor='John Cleese')  # Unbekanntes Schluesselwort.

Allgemein gilt, daß Positions-Argumente vor Schlüssel-Argumenten in einer Argumentliste stehen müssen, wobei die Schlüssel aus den formalen Parameternamen gewählt werden müssen. Es ist unwichtig, ob ein formaler Parameter einen Vorgabewert hat oder nicht. Keinem Argument darf ein Wert mehr als einmal zugewiesen werden - Namen von formalen Parametern, die mit Positions-Argumenten korrespondieren, können nicht als Schlüssel im gleichen Aufruf verwendet werden.

Wenn ein letzter formaler Parameter der Form **name existiert, so wird ihm ein Dictionary zugewiesen, der alle Schlüssel-Argumente enthält, deren Schlüssel nicht mit einem formalen Parameter korrespondiert. Das darf kombiniert werden mit einem formalen Parameter der Form *name (beschrieben im nächsten Unterabschnitt), der ein Tupel mit den Positions-Argumenten zugewiesen bekommt, die zusätzlich zu denen der formalen Parameterliste existieren. (*name muß vor **name stehen.) Wenn wir z.B. die folgende Funktion definieren:


def cheeseshop(kind, *arguments, **keywords):
    print "-- Do you have any", kind, '?'
    print "-- I'm sorry, we're all out of", kind
    for arg in arguments: print arg
    print '-'*40
    for kw in keywords.keys(): print kw, ':', keywords[kw]

könnte sie wie folgt aufgerufen werden:


cheeseshop('Limburger', "It's very runny, sir.",
           "It's really very, VERY runny, sir.",
           client='John Cleese',
           shopkeeper='Michael Palin',
           sketch='Cheese Shop Sketch')

und natürlich bestünde die Ausgabe in:


-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
client : John Cleese
shopkeeper : Michael Palin
sketch : Cheese Shop Sketch


4.7.3 Variable Argumentlisten

Schließlich besteht die am wenigsten benutzte Möglichkeit darin, daß eine Funktion mit einer beliebigen Anzahl von Argumenten aufgerufen werden kann. Diese Argumente werden in einem Tupel zusammengefaßt. Vor der variablen Anzahl von Argumenten können beliebig viele normale Argumente stehen (auch keine).


def fprintf(file, format, *args):
    file.write(format % args)


4.7.4 Lambda-Formen

Wegen der großen Nachfrage wurden einige der üblichen Eigenschaften von funktionalen Programmiersprachen in Python aufgenommen. Mit dem lambda-Schlüsselwort können kleine, anonyme Funktionen erzeugt werden. Dies ist eine Funktion, die die Summe zweier Argumente zurück gibt: "lambda a, b: a+b". Lambda-Formen können verwendet werden, wann immer Funktions-Objekte benötigt werden. Syntaktisch sind sie beschränkt auf einen einzigen Ausdruck. Semantisch sind sie nichts als ein syntaktisches Zuckerl für eine normale Funktionsdefinition. Wie bei verschachtelten Funktionsdefinitionen können lambda-Formen keine Variablen des äußeren Geltungsbereichs referenzieren, aber das kann durch vernünftige Verwendung von Argumenten mit Vorgabewerten umgangen werden, z.B.:


def make_incrementor(n):
    return lambda x, incr=n: x+incr


4.7.5 Dokumentations-Strings

Allmählich formieren sich Konventionen über den Inhalt und das Format von Dokumentations-Strings.

Die erste Zeile sollte immer eine sehr knappe Zusammenfassung der Aufgabe des Objektes sein. Um es kurz zu machen, sollte sie nicht explizit den Namen oder Typ des Objektes enthalten, da diese mit anderen Mitteln zur Verfügung stehen (außer, wenn der Name ein Verb ist, das die Operation einer Funktion beschreibt). Diese Zeile sollte mit einem Großbuchstaben beginnen und mit einem Punkt enden.

Falls der Docstring noch mehr Zeilen enthält, sollte die zweite Zeile leer sein, um eine sichtbare Trennung von Zusammenfassung und Rest der Beschreibung vorzunehmen. Die folgenden Zeilen sollten ein oder mehrere Absätze sein, die Aufrufkonventionen, Seiteneffekte, etc. des Objektes beschreiben.

Der Python-Parser belässt die Einrückung von mehrzeiligen String-Literalen, d.h. daß Dokumentations-Werkzeuge diese Einrückung selbst entfernen müssen. Dies kann mit den folgenden Konventionen geschehen: Die erste nicht-leere Zeile nach der ersten Zeile des Strings bestimmt das Maß der Einrückung für den gesamten Docstring. (Wir können die erste Zeile nicht auswerten, da sie normalerweise direkt nach den - eingerückten - öffnenden Anführungszeichen kommt, so daß ihre Einrückung im String-Literal nicht ersichtlich ist.) Leerzeichen, die ,,äquivalent`` zu dieser Einrückung sind, werden dann vom linken Rand aller Zeilen entfernt. Zeilen, die weniger eingerückt sind, sollten nicht vorkommen, aber wenn doch, sollte der gesamte linke Leerraum entfernt werden. Der Test auf Leerraum sollte nach Expansion von Tabulatoren (meist auf acht Zeichen) erfolgen.



Fußnoten

... value).4.1
Tatsächlich wäre Objekt-Referenz-Semantik (engl. call by object reference) eine bessere Beschreibung, da wenn ein veränderliches Objekt übergeben wird, die aufrufende Funktion alle von der aufgerufenen Funktion daran vorgenommen Änderungen sehen wird, z.B. Elemente, die in einer Liste eingefügt wurden.
... erzeugt.4.2
Die aufgerufene Funktion kann nicht auf die lokalen Symbole der aufrufenden Funktion zugreifen, wenn diese nicht als Parameter übergeben werden. [Der Übersetzer]


Send comments to python-docs@python.org.