Hat Python einen ternären Bedingungsoperator?


Answers

Sie können in ein Tupel indizieren:

(falseValue, trueValue)[test]

test muss True oder False zurückgeben .
Es könnte sicherer sein, es immer als:

(falseValue, trueValue)[test == True]

oder Sie können die integrierte bool() , um einen Boolean Wert zu gewährleisten:

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

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




Ja.

>>> b = (True if 5 > 4 else False)
>>> print b
True



Hat Python einen ternären Bedingungsoperator?

Ja. Aus der Grammatikdatei :

test: or_test ['if' or_test 'else' test] | lambdef

Der Teil von Interesse ist:

or_test ['if' or_test 'else' test]

Eine ternäre bedingte Operation hat also die Form:

expression1 if expression2 else expression3

expression3 wird träge ausgewertet (dh nur ausgewertet, wenn expression2 in einem booleschen Kontext falsch ist). Und aufgrund der rekursiven Definition können Sie sie unbegrenzt verketten (auch wenn es sich um einen schlechten Stil handelt).

expression1 if expression2 else expression3 if expression4 else expression5 # and so on

Ein Hinweis zur Verwendung:

Beachten Sie, dass jedem if ein else folgen muss. Leute, die Lernlisten-Comprehensions und Generator-Ausdrücke lernen, können dies als eine schwierige Lektion empfinden - das Folgende wird nicht funktionieren, da Python einen dritten Ausdruck für ein else erwartet:

[expression1 if expression2 for element in iterable]
#                          ^-- need an else here

was einen SyntaxError: invalid syntax . Also ist das Obige entweder ein unvollständiges Stück Logik (vielleicht erwartet der Benutzer ein No-Op in der falschen Bedingung) oder es könnte beabsichtigt sein, expression2 als Filter zu verwenden - stellt fest, dass das Folgende legales Python ist:

[expression1 for element in iterable if expression2]

expression2 funktioniert als Filter für das Listenverständnis und ist kein ternärer Bedingungsoperator.

Alternative Syntax für einen engeren Fall:

Sie können es etwas schmerzhaft finden, Folgendes zu schreiben:

expression1 if expression1 else expression2

expression1 muss zweimal mit der obigen Verwendung ausgewertet werden. Es kann die Redundanz begrenzen, wenn es sich lediglich um eine lokale Variable handelt. Ein gebräuchliches und performantes Python-Idiom für diesen Anwendungsfall ist jedoch das Abkürzungsverhalten:

expression1 or expression2

was in der Semantik äquivalent ist. Beachten Sie, dass einige Styleguides diese Verwendung aus Gründen der Übersichtlichkeit einschränken können - sie enthält eine Menge Bedeutung in sehr wenig Syntax.




Ein Operator für einen bedingten Ausdruck in Python wurde 2006 als Teil des Python-Erweiterungsvorschlags 308 hinzugefügt. Seine Form unterscheidet sich von üblichen ?: Operator 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 faul ausgewertet werden .

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 von and und or Operatoren:

result = (a > b) and x or y

Dies funktioniert jedoch nicht, wenn x False .

Eine mögliche Problemumgehung besteht darin, x und y Listen oder Tupel wie folgt zu erstellen:

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

oder:

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

Wenn Sie mit Wörterbüchern arbeiten, können Sie anstelle der Verwendung einer ternären Bedingung die Funktion get(key, default) , z.

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

Quelle: ?:




Für Python 2.5 und neuer gibt es eine spezifische 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

Es gibt jedoch ein potenzielles Problem, bei dem, wenn cond als True ausgewertet wird und on_true zu False ausgewertet wird, on_false anstelle von 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.




Mehr ein Tipp als eine Antwort (ich muss das Offensichtliche nicht zum hundertsten Mal wiederholen), aber ich benutze es manchmal als eine oneliner Abkürzung in solchen Konstrukten:

if conditionX:
    print('yes')
else:
    print('nah')

, wird:

print('yes') if conditionX else print('nah')

Manche (viele :) mögen es als unpythonisch (sogar, rubinisch) ansehen, aber ich persönlich finde es natürlicher - dh wie du es normalerweise ausdrücken würdest, plus ein bisschen mehr ansprechend in großen Code-Blöcken.




Es gibt eine ternäre Option, wie in anderen Antworten angegeben, aber Sie können sie auch mit "oder" simulieren, wenn Sie einen booleschen Wert oder keinen Wert prüfen:

>>> a = False
>>> b = 5
>>> a or b
5

>>> a = None
>>> a or b
5



Ausdruck1 wenn 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



In [1]: a = 1 if False else 0

In [2]: a
Out[2]: 0

In [3]: b = 1 if True else 0

In [4]: b
Out[4]: 1



Du wirst es oft finden

cond and on_true or on_false

aber das führt zu einem Problem, wenn on_true == 0

>>> x = 0
>>> print x == 0 and 0 or 1 
1
>>> x = 1
>>> print x == 0 and 0 or 1 
1

wo Sie für einen normalen ternären Operator dieses Ergebnis erwarten würden

>>> x = 0
>>> print 0 if x == 0 else 1 
0
>>> x = 1
>>> print 0 if x == 0 else 1 
1



Related