Frage Hat Python einen ternären Bedingungsoperator?


Wenn Python keinen ternären Bedingungsoperator hat, ist es möglich, einen mit anderen Sprachkonstrukten zu simulieren?


4427


Ursprung


Antworten:


Ja, war es hinzugefügt in Version 2.5.
Die Syntax lautet:

a if condition else b

Zuerst condition wird ausgewertet, dann entweder a oder b wird basierend auf der zurückgegeben Boolesch Wert von condition
Ob condition bewertet zu Wahr  a wird zurückgegeben, sonst b ist zurück gekommen.

Beispielsweise:

>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'

Beachten Sie, dass Bedingungen ein sind Ausdruck, kein Erklärung. Dies bedeutet, dass Sie keine Zuweisungen oder verwenden können pass oder andere Anweisungen in einem Konditional:

>>> pass if False else x = 3
  File "<stdin>", line 1
    pass if False else x = 3
          ^
SyntaxError: invalid syntax

In einem solchen Fall müssen Sie ein normales verwenden if Anweisung statt einer Bedingung.


Denken Sie daran, dass es von einigen Pythonisten aus verschiedenen Gründen verpönt ist:

  • Die Reihenfolge der Argumente unterscheidet sich von vielen anderen Sprachen (wie C, Ruby, Java usw.), was zu Fehlern führen kann, wenn Leute, die nicht mit dem "überraschenden" Verhalten von Python vertraut sind, es benutzen (sie können die Reihenfolge umkehren).
  • Manche finden es "unhandlich", da es dem normalen Gedankenfluss widerspricht (Denken zuerst an den Zustand und dann an die Effekte).
  • Stilistische Gründe.

Wenn Sie Schwierigkeiten haben, sich an die Reihenfolge zu erinnern, dann denken Sie daran, dass wenn Sie es laut vorlesen, Sie (fast) sagen, was Sie meinen. Beispielsweise, x = 4 if b > 8 else 9 wird laut vorgelesen x will be 4 if b is greater than 8 otherwise 9.

Offizielle Dokumentation:


5285



Sie können in ein Tupel indizieren:

(falseValue, trueValue)[test]

test muss zurückkehren Wahr oder Falsch.
Es könnte sicherer sein, es immer als:

(falseValue, trueValue)[test == True]

oder Sie können das eingebaute verwenden bool() versichern a Boolesch Wert:

(falseValue, trueValue)[bool(<expression>)]

591



Für Versionen vor 2.5 gibt es den Trick:

[expression] and [on_true] or [on_false]

Es kann zu falschen Ergebnissen führen on_true   hat einen falschen booleschen Wert.1
Obwohl es den Vorteil hat, Ausdrücke von rechts nach links zu bewerten, was meiner Meinung nach klarer ist.

1. Gibt es ein Äquivalent von C "?:" Ternärer Operator?


245



Ausdruck1 ob Bedingung sonst Ausdruck2

>>> a = 1
>>> b = 2
>>> 1 if a > b else -1 
-1
>>> 1 if a > b else -1 if a < b else 0
-1

155



Von die Dokumentation:

Bedingte Ausdrücke (manchmal als "ternärer Operator" bezeichnet) haben die niedrigste Priorität aller Python-Operationen.

Der Ausdruck x if C else y wertet zuerst den Zustand aus, C (nicht x); ob C ist wahr, x wird ausgewertet und sein Wert wird zurückgegeben; Andernfalls, y wird ausgewertet und sein Wert wird zurückgegeben.

Sehen PEP 308 Weitere Informationen zu bedingten Ausdrücken

Neu seit Version 2.5.


105



Ein Operator für einen bedingten Ausdruck in Python wurde 2006 als Teil von hinzugefügt Python-Verbesserungsvorschlag 308. Seine Form unterscheidet sich von der allgemeinen ?: Betreiber und es ist:

<expression1> if <condition> else <expression2>

was entspricht:

if <condition>: <expression1> else: <expression2>

Hier ist ein Beispiel:

result = x if a > b else y

Eine andere Syntax, die verwendet werden kann (kompatibel mit Versionen vor 2.5):

result = (lambda:y, lambda:x)[a > b]()

Wo Operanden sind faul bewertet.

Eine andere Möglichkeit besteht darin, ein Tupel zu indizieren (das nicht mit dem Bedingungsoperator der meisten anderen Sprachen übereinstimmt):

result = (y, x)[a > b]

oder explizit konstruiertes Wörterbuch:

result = {True: x, False: y}[a > b]

Eine andere (weniger zuverlässige), aber einfachere Methode ist die Verwendung and und or Betreiber:

result = (a > b) and x or y

Dies funktioniert jedoch nicht, wenn x wäre False.

Ein möglicher Workaround ist zu machen x und y Listen oder Tupel wie im Folgenden:

result = ((a > b) and [x] or [y])[0]

oder:

result = ((a > b) and (x,) or (y,))[0]

Wenn Sie mit Wörterbüchern arbeiten, anstatt eine ternäre Bedingung zu verwenden, können Sie davon profitieren get(key, default), beispielsweise:

shell = os.environ.get('SHELL', "/bin/sh")

Quelle: ?: in Python bei Wikipedia


78



@oben:

Leider

(falseValue, trueValue)[test]

Lösung hat kein Kurzschlussverhalten; Daher werden sowohl falseValue als auch trueValue unabhängig von der Bedingung ausgewertet. Dies könnte suboptimal oder sogar fehlerhaft sein (d. H. Sowohl trueValue als auch falseValue können Methoden sein und Nebenwirkungen haben).

Eine Lösung dafür wäre

(lambda: falseValue, lambda: trueValue)[test]()

(Ausführung verzögert, bis der Gewinner bekannt ist;)), aber es führt zu Inkonsistenz zwischen aufrufbaren und nicht aufrufbaren Objekten. Außerdem löst es nicht den Fall, wenn Eigenschaften verwendet werden.

Und so die Geschichte geht - die Wahl zwischen 3 erwähnten Lösungen ist ein Kompromiss zwischen der Kurzschluss-Feature, mit mindestens Python 2.5 (IMHO kein Problem mehr) und nicht anfällig für "TrueValue-wertet-zu-Falsch" Fehler.


72



Für Python 2.5 und neuer gibt es eine spezielle Syntax:

[on_true] if [cond] else [on_false]

In älteren Pythons ist kein ternärer Operator implementiert, aber es ist möglich ihn zu simulieren.

cond and on_true or on_false

Allerdings gibt es ein potenzielles Problem, welches, wenn cond bewertet zu True und on_true bewertet zu False dann on_false wird anstelle von zurückgegeben on_true. Wenn Sie dieses Verhalten wünschen, ist die Methode in Ordnung, ansonsten verwenden Sie diese:

{True: on_true, False: on_false}[cond is True] # is True, not == True

welche verpackt werden kann durch:

def q(cond, on_true, on_false)
    return {True: on_true, False: on_false}[cond is True]

und so benutzt:

q(cond, on_true, on_false)

Es ist mit allen Python-Versionen kompatibel.


48