2.11. Conditionals

Eine Bedingung führt einen Codeblock nur dann aus, wenn ein Test als wahr ausgewertet wird. Das Schlüsselwort ist if, optional gefolgt von einem oder mehreren elif-Zweigen („else if“) und einem abschließenden else.

n = 42

if n > 0:
    print("positive")
elif n < 0:
    print("negative")
else:
    print("zero")

Der Rumpf jedes Zweigs ist alles, was darunter eingerückt ist (per Konvention vier Leerzeichen). Python durchläuft die Zweige der Reihe nach, führt den ersten aus, dessen Test wahr ist, und überspringt den Rest. Der else-Block läuft nur, wenn jeder vorangehende Test falsch war; er ist immer optional.

Ein Flussdiagramm, das if/elif/else zeigt: zwei rautenförmige Entscheidungstests mit ihren Rümpfen, die zu einem abschließenden else-Rumpf durchfallen, wenn beide Tests falsch sind.

Es läuft immer nur ein Zweig. Tests werden von oben nach unten ausgewertet, bis einer erfolgreich ist; der Rest wird übersprungen.

2.11.1. Wahrheitswert

Ein Test in einem if muss nicht True oder False zurückgeben – jeder Wert zählt entweder als truthy oder falsy. Die falsy-Werte sind:

  • False und None

  • Die Zahl Null: 0, 0.0

  • Leere Folgen und Sammlungen: "", [], (), {}, b""

Alles andere ist truthy. Damit können Sie kompakte Tests schreiben:

if name:                     # false on empty string
    print("hello", name)

if items:                    # false on empty list, dict, etc.
    process(items)

Beachten Sie, dass der Wahrheitswert die Bedeutung verändert. if value: ist nicht dasselbe wie if value is not None: – das erste ist auch dann falsch, wenn value 0 oder "" ist. Wenn Sie wirklich „ist dies genau None“ meinen, verwenden Sie ausdrücklich is None / is not None.

2.11.2. Ternäre Ausdrücke

Eine Bedingung kann innerhalb eines Ausdrucks erscheinen:

label = "even" if n % 2 == 0 else "odd"

Lesen Sie als „label ist "even" wenn n % 2 == 0 sonst "odd".“ Praktisch für Einzeiler; für alles, was länger als eine Zeile ist, lässt sich eine vollständige if-Anweisung leichter lesen.

2.11.3. Verschachtelung und frühe Rückgaben

Bedingungen können beliebig tief verschachtelt werden, aber jede zusätzliche Einrückungsebene macht eine Funktion schwerer lesbar. Das folgende Beispiel prüft vier Bedingungen, bevor es die eigentliche Arbeit erledigt, und lässt die nützliche Zeile vier Einrückungen tief vergraben:

def process(item):
    if item is not None:
        if item.is_valid():
            if item.size() > 0:
                if item.owner == "me":
                    return do_the_work(item)
    return None

Zwei Muster glätten diese Art von Code.

2.11.3.1. Frühe Rückgaben für Wächter

Behandeln Sie jeden „Abbruch“-Fall zuerst, jeweils mit einem eigenen return, sodass die Hauptlogik auf der äußeren Einrückung bleibt. Jeder Wächter liest sich als „dies ist kein Fall, den wir behandeln; verlassen“:

def process(item):
    if item is None:
        return None
    if not item.is_valid():
        return None
    if item.size() == 0:
        return None
    if item.owner != "me":
        return None
    return do_the_work(item)

Der „Hauptpfad“ ist jetzt eine Zeile am Ende der Funktion, nicht in vier Ebenen vergraben. Dieser Stil wird manchmal als Guard-Clause-Muster bezeichnet.

2.11.3.2. Tests mit and / or kombinieren

Wenn mehrere Bedingungen alle für denselben Zweig gelten müssen, kombinieren Sie sie mit and statt sie zu verschachteln. Bedingungen, die den Zweig jeweils unabhängig auslösen, kombinieren Sie mit or:

# all must hold -- use `and`
if user.is_admin() and user.has_permission("write") and not locked:
    save()

# any one of them is enough -- use `or`
if c == " " or c == "\t" or c == "\n":
    whitespace_count += 1

Beide Formen werten kurzgeschlossen aus, sodass eine teure Prüfung auf der rechten Seite nur dann läuft, wenn die günstigeren Prüfungen auf der linken Seite die Frage nicht bereits geklärt haben.