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.
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:
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.