Ist Python haben einen ternären bedingten Operator?
-
23-08-2019 - |
Frage
Wenn Python keine ternäre Konditionaloperator hat, ist es möglich, eine mit anderen Sprachkonstrukten zu simulieren?
Lösung
Ja, es war hinzugefügt in Version 2.5. Der Ausdruck Syntax:
a if condition else b
Erste condition
ausgewertet wird, dann genau ein von entweder a
oder b
ausgewertet und zurück basierend auf dem Boolean Wert von condition
. Wenn condition
True
auswertet, dann wird a
ausgewertet und zurückgegeben aber b
wird ignoriert, oder aber, wenn b
ausgewertet und zurückgegeben aber a
ignoriert.
Dies ermöglicht einen Kurzschluss, denn wenn condition
wahr ist nur a
ausgewertet wird und b
wird überhaupt nicht ausgewertet, aber wenn condition
falsch ist nur b
ausgewertet und a
wird überhaupt nicht bewertet.
Zum Beispiel:
>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'
Beachten Sie, dass conditionals ist eine Ausdruck , kein Aussage . Dies bedeutet, dass Sie nicht Zuweisungsanweisungen oder pass
oder andere Aussagen innerhalb eines bedingten Ausdrucks verwenden können:
>>> pass if False else x = 3
File "<stdin>", line 1
pass if False else x = 3
^
SyntaxError: invalid syntax
Sie können jedoch verwenden bedingte Ausdrücke eine Variable zuweisen wie folgt:
x = a if True else b
Denken Sie an den bedingten Ausdruck als zwischen zwei Werten umgeschaltet wird. Es ist sehr nützlich, wenn Sie in einem 'ein Wert oder eine andere Situation sind, es aber viel anderes nicht tun.
Wenn Sie Aussagen verwenden, haben Sie eine normale if
verwenden Aussage anstelle eines bedingten Ausdruck .
Beachten Sie, dass es bei einigen von Pythonistas aus mehreren Gründen verpönt ist:
- Die Reihenfolge der Argumente unterscheidet sich von denen des klassischen
condition ? a : b
ternäre Operator von vielen anderen Sprachen (wie C, C ++, Go, Perl, Ruby, Java, Javascript, etc.), die zu Fehlern führen können, wenn die Menschen nicht vertraut mit Python „überraschend“ Verhalten verwendet es (sie das Argument Reihenfolge umkehren kann). - Manche finden es „sperrig“, da es (erstes Denken der Bedingung und dann die Effekte) auf den normalen Gedankenfluss entgegen geht.
- stilistische Gründe. (Obwohl die 'inline
if
' sein kann wirklich nützlich, und Ihr Skript machen prägnante, tut es kompliziert Ihren Code wirklich)
Wenn Sie Probleme haben, den Auftrag zu erinnern, dann ist das erinnern, als laut zu lesen, Sie (fast) sagen, was Sie meinen. Zum Beispiel wird x = 4 if b > 8 else 9
als x will be 4 if b is greater than 8 otherwise 9
vorlas.
Offizielle Dokumentation:
Andere Tipps
Sie können Index in ein Tupel:
(falseValue, trueValue)[test]
test
muss zurückkehren True oder False .
Es könnte sicherer sein, immer zu implementieren als:
(falseValue, trueValue)[test == True]
oder Sie können die eingebaute in bool()
Boolean Wert zu gewährleisten:
(falseValue, trueValue)[bool(<expression>)]
Für ältere Versionen bis 2.5, gibt es den Trick:
[expression] and [on_true] or [on_false]
Es kann falsche Ergebnisse, wenn on_true
hat einen falschen Booleschen Wert. 1
Obwohl hat es den Vorteil haben Ausdrücke von links nach rechts der Bewertung, die meiner Meinung nach klarer ist.
1. Gibt es eine äquivalent von C-Schema „:“? ternärer Operator
<expression 1> if <condition> else <expression 2>
a = 1
b = 2
1 if a > b else -1
# Output is -1
1 if a > b else -1 if a < b else 0
# Output is -1
Bedingte Ausdrücke (manchmal auch als ein „ternärer Operator“) hat die niedrigste Priorität aller Python-Operationen.
Der Ausdruck
x if C else y
wertet zunächst die Bedingung, C ( nicht x ); wenn C ist wahr, x wird ausgewertet, und sein Wert wird zurückgegeben; andernfalls y wird ausgewertet und ihr Wert zurückgegeben wird.Siehe PEP 308 weitere Einzelheiten zu dem Bedingungsausdrücken.
Neu seit Version 2.5.
Ein Operator für einen bedingten Ausdruck in Python wurde 2006 als Teil der Python Erweiterung hinzugefügt Vorschlag 308 . Seine Form unterscheiden sich von gemeinsamen ?:
Operator und es ist:
<expression1> if <condition> else <expression2>
das ist äquivalent zu:
if <condition>: <expression1> else: <expression2>
Hier ist ein Beispiel:
result = x if a > b else y
Eine andere Syntax, die (kompatibel mit Versionen vor 2.5) verwendet werden können:
result = (lambda:y, lambda:x)[a > b]()
Dabei gilt Operanden lazily ausgewertet .
Eine andere Möglichkeit ist durch ein Tupel Indizierung (die mit dem Bedingungsoperator von den meisten anderen Sprachen nicht konsistent ist):
result = (y, x)[a > b]
oder explizit konstruiert Wörterbuch:
result = {True: x, False: y}[a > b]
Eine andere (weniger zuverlässig), aber einfachere Methode ist and
und or
Operatoren zu verwenden:
result = (a > b) and x or y
jedoch wird dies nicht funktionieren, wenn x
False
würde.
Eine mögliche Abhilfe ist, machen x
und y
Listen oder Tupeln wie im folgenden Beispiel:
result = ((a > b) and [x] or [y])[0]
oder:
result = ((a > b) and (x,) or (y,))[0]
Wenn Sie mit Wörterbuch arbeiten, anstatt mit einem ternären bedingten, können Sie nutzen get(key, default)
, zum Beispiel:
shell = os.environ.get('SHELL', "/bin/sh")
Quelle: : in Python bei Wikipedia
Leider ist die
(falseValue, trueValue)[test]
Lösung hat kein Kurzschlussverhalten; also sowohl falseValue
und trueValue
werden unabhängig von der Bedingung ausgewertet. Diese suboptimal sein könnte oder sogar Buggy (das heißt sowohl trueValue
und falseValue
Verfahren sein könnte und haben Nebenwirkungen).
Eine Lösung hierfür wäre
(lambda: falseValue, lambda: trueValue)[test]()
(Ausführung verzögert, bis der Sieger bekannt ist;)), aber es führt Inkonsistenz zwischen aufrufbar und unkündbaren Objekten. Darüber hinaus löst es nicht der Fall, wenn Eigenschaften verwendet wird.
Und so geht die Geschichte - die Wahl zwischen 3 genannten Lösungen ist ein Kompromiss zwischen dem Kurzschluss Merkmale, zumindest mit Зython 2.5 (IMHO kein Problem mehr) und nicht in die anfällig für „trueValue
-auswertet-to -false“Fehler.
Ternary Operator in verschiedenen Programmiersprachen
Hier versuche ich nur einigen wichtigen Unterschied in ternary operator
zwischen ein paar Programmiersprachen zu zeigen.
Ternary Operator in Javascript
var a = true ? 1 : 0;
# 1
var b = false ? 1 : 0;
# 0
Ternary Operator in Ruby
a = true ? 1 : 0
# 1
b = false ? 1 : 0
# 0
Ternary Operator in Scala
val a = true ? 1 | 0
# 1
val b = false ? 1 | 0
# 0
Ternary Operator in R Programmierung
a <- if (TRUE) 1 else 0
# 1
b <- if (FALSE) 1 else 0
# 0
Ternary Operator in Python
a = 1 if True else 0
# 1
b = 1 if False else 0
# 0
Für Python 2.5 und neuere gibt es eine spezifische Syntax:
[on_true] if [cond] else [on_false]
Bei älteren Pythons ein ternärer Operator ist nicht implementiert, aber es ist möglich, es zu simulieren.
cond and on_true or on_false
Obwohl, gibt es ein potenzielles Problem, das wenn cond
ausgewertet True
und on_true
ausgewertet False
dann on_false
statt on_true
zurückgeführt wird. Wenn Sie dieses Verhalten wollen dies die Methode ist in Ordnung, sonst verwenden:
{True: on_true, False: on_false}[cond is True] # is True, not == True
, die durch verpackenden kann:
def q(cond, on_true, on_false)
return {True: on_true, False: on_false}[cond is True]
und auf diese Weise verwendet:
q(cond, on_true, on_false)
Es ist kompatibel mit allen Python-Versionen.
Sie können oft finden
cond and on_true or on_false
, aber diese führen zu 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 sich für einen normalen ternären Operator erwarten dieses Ergebnis
>>> x = 0
>>> print 0 if x == 0 else 1
0
>>> x = 1
>>> print 0 if x == 0 else 1
1
Ist Python haben einen ternären bedingten Operator?
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]
So eine ternäre bedingte Operation ist von der Form:
expression1 if expression2 else expression3
expression3
wird träge ausgewertet werden (das heißt, nur ausgewertet, wenn expression2
in einem Booleschen Kontext falsch ist). Und wegen der rekursiven Definition können Sie ketten sie auf unbestimmte Zeit (obwohl es schlechter Stil kann.)
expression1 if expression2 else expression3 if expression4 else expression5 # and so on
Ein Hinweis auf Nutzung:
Beachten Sie, dass jeder if
muss mit einem else
folgen. Menschen Listenkomprehensionen und Generator Ausdrücke lernen können finden dies eine schwierige Lektion zu lernen - das Folgende nicht funktionieren, da Python einen dritten Ausdruck für ein anderes erwartet:
[expression1 if expression2 for element in iterable]
# ^-- need an else here
, die wirft eine SyntaxError: invalid syntax
.
So ist die oben entweder ein unvollständiges Stück Logik ist (vielleicht der Benutzer erwartet ein No-op in der falschen Zustand) oder was kann jetzt höher sein als Filter verwenden expression2 - stellt fest, dass die folgenden Rechts Python ist:
[expression1 for element in iterable if expression2]
expression2
arbeitet als Filter für die Liste Verständnis, und ist nicht ein ternäres Konditionaloperator.
Alternative Syntax für einen engeren Fall:
Sie können es etwas schmerzhaft folgendes zu schreiben:
expression1 if expression1 else expression2
expression1
müssen zweimal mit der obenen Nutzung bewertet werden. Es kann Redundanz begrenzen, wenn es einfach eine lokale Variable ist. Allerdings ist ein gemeinsames und performant Pythonic Idiom für diesen Anwendungsfall ist or
des shortcutting Verhalten zu verwenden:
expression1 or expression2
, das entspricht in der Semantik. Beachten Sie, dass einige Stil-Führer aus Gründen der Klarheit diese Nutzung einschränken können -. Es viel Sinn in sehr wenig Syntax nicht packen
Simulieren des Python ternären Operators.
Zum Beispiel
a, b, x, y = 1, 2, 'a greather than b', 'b greater than a'
result = (lambda:y, lambda:x)[a > b]()
Ausgabe:
'b greater than a'
Sie können dies tun: -
[condition] and [expression_1] or [expression_2] ;
Beispiel: -
print(number%2 and "odd" or "even")
Dies würde „ungerade“ drucken, wenn die Zahl ungerade oder „gerade“, wenn die Zahl gerade ist.
Das Ergebnis: -. Wenn Bedingung wahr Exp_1 ist ausgeführt, sonst exp_2 ausgeführt wird
Hinweis: - 0, None, False emptylist, bewertet Leerstring als Falsch. Und alle anderen Daten als 0 den Wert true.
Hier ist, wie es funktioniert:
, wenn die Bedingung [Bedingung] wird „True“ dann, expression_1 ausgewertet werden, aber nicht Ausdruck_2. Wenn wir „und“ etwas mit 0 (Null), wird das Ergebnis immer Fasle .So in der folgenden Aussage sein,
0 and exp
Der Ausdruck exp überhaupt nicht bewertet werden, da „und“ mit 0 wird immer auf Null bewerten und es besteht keine Notwendigkeit, den Ausdruck auszuwerten. Dies ist, wie der Compiler selbst arbeitet, in allen Sprachen.
1 or exp
der Ausdruck exp wird überhaupt nicht bewertet werden, da „oder“ mit 1 immer 1 sein wird, so wird es nicht die Mühe, den Ausdruck exp zu bewerten, da das Ergebnis 1 ohnehin sein wird. (Compiler-Optimierungsverfahren).
Aber im Fall von
True and exp1 or exp2
Der zweite Ausdruck exp2 nicht da True and exp1
ausgewertet wird wahr wäre, wenn exp1 nicht falsch ist.
ähnlich in
False and exp1 or exp2
Der Ausdruck exp1 wird nicht ausgewertet werden, da False Schreiben 0 und tun entspricht „und“ mit 0 würde 0 selbst, aber nach exp1 da „oder“ verwendet wird, wird es den Ausdruck exp2 nach „oder“ bewerten.
Hinweis: - Diese Art der Verzweigung mit „oder“ und „und“ kann nur verwendet werden, wenn die expression_1 keinen Wahrheitswert False (oder 0 oder None oder emptylist hat [] oder Leerstring ‚‘.), da, wenn expression_1 falsch wird, dann wird die Ausdruck_2 wegen der Anwesenheit ausgewertet werden „oder“ zwischen Exp_1 und exp_2.
Falls Sie noch, um es für alle Fälle funktioniert unabhängig davon, was Exp_1 und exp_2 Wahrheitswerte sind, dies zu tun: -
[condition] and ([expression_1] or 1) or [expression_2] ;
Ternary Konditionaloperator einfach ermöglicht eine Bedingung in einer einzigen Zeile Testen der mehrzeiligen ersetzen if-else den Code kompakt zu machen.
Syntax:
[on_true], wenn [Ausdruck] sonst [on_false]
1- einfache Methode ternären Operator zu verwenden:
# Program to demonstrate conditional operator
a, b = 10, 20
# Copy value of a in min if a < b else copy b
min = a if a < b else b
print(min) # Output: 10
2- Direkte Methode der Verwendung von Tupeln, Wörterbuch und Lambda:
# Python program to demonstrate ternary operator
a, b = 10, 20
# Use tuple for selecting an item
print( (b, a) [a < b] )
# Use Dictionary for selecting an item
print({True: a, False: b} [a < b])
# lamda is more efficient than above two methods
# because in lambda we are assure that
# only one expression will be evaluated unlike in
# tuple and Dictionary
print((lambda: b, lambda: a)[a < b]()) # in output you should see three 10
3- Ternary Operator kann geschrieben werden als verschachtelte if-else:
# Python program to demonstrate nested ternary operator
a, b = 10, 20
print ("Both a and b are equal" if a == b else "a is greater than b"
if a > b else "b is greater than a")
Vor Ansatz kann geschrieben werden:
# Python program to demonstrate nested ternary operator
a, b = 10, 20
if a != b:
if a > b:
print("a is greater than b")
else:
print("b is greater than a")
else:
print("Both a and b are equal")
# Output: b is greater than a
Mehr Spitze als eine Antwort (müssen nicht die offensichtlich für den hundertsten Mal wiederholen), aber ich es manchmal als oneliner Verknüpfung verwenden in solchen Konstrukten:
if conditionX:
print('yes')
else:
print('nah')
wird:
print('yes') if conditionX else print('nah')
Einige (viele :) Stirnrunzeln kann es als unpythonic (auch, Rubin-ish :), aber ich persönlich finde es natürlich - das heißt, wie man es normalerweise ausdrücken würde, plus ein bisschen mehr optisch ansprechend in großen Blöcken von Code.
a if condition else b
Gerade diese Pyramide merken, wenn Sie Probleme haben, zu erinnern:
condition
if else
a b
JA, hat Python einen ternären Operator, hier ist die Syntax und ein Beispiel-Code, das gleiche zu demonstrieren:)
#[On true] if [expression] else[On false]
# if the expression evaluates to true then it will pass On true otherwise On false
a= input("Enter the First Number ")
b= input("Enter the Second Number ")
print("A is Bigger") if a>b else print("B is Bigger")
Viele Programmiersprachen von C
abgeleitet haben in der Regel die folgende Syntax ternarer Konditionaloperator:
<condition> ? <expression1> : <expression2>
Zuerst die
Python
B enevolent D ictator F oder L ife (ich meine, Guido van Rossum natürlich) abgelehnt (als nicht-Pythonic Stil), da es sehr schwer ist, zu verstehen, für die MenschenC
Sprache nicht verwendet. Auch die Doppelpunkt-Zeichen:
hat bereits viele Anwendungen inPython
. Nach dem PEP 308 genehmigt wurde,Python
schließlich seine eigene Verknüpfung bedingten Ausdruck erhalten (was wir verwenden jetzt):
<expression1> if <condition> else <expression2>
Also, zunächst wertet sie die Bedingung. Wenn es True
zurückkehrt, expression1 wird ausgewertet um das Ergebnis zu geben, sonst expression2 ausgewertet. Aufgrund Lazy Evaluation Mechanik -. Nur ein Ausdruck ausgeführt wird,
Hier einige Beispiele sind (Bedingungen werden von links nach rechts ausgewertet werden):
pressure = 10
print('High' if pressure < 20 else 'Critical')
# Result is 'High'
Ternary Operatoren können in Reihe verkettet werden:
pressure = 5
print('Normal' if pressure < 10 else 'High' if pressure < 20 else 'Critical')
# Result is 'Normal'
Das folgende ist die gleiche wie vorherige:
pressure = 5
if pressure < 20:
if pressure < 10:
print('Normal')
else:
print('High')
else:
print('Critical')
# Result is 'Normal'
Hope, das hilft.
Eine der Alternativen zu Python bedingter Ausdruck ist die folgende:
{True:"yes", False:"no"}[boolean]
, die hat die folgende nette Erweiterung:
{True:"yes", False:"no", None:"maybe"}[boolean_or_none]
Der kürzeste alterativ bleibt:
("no", "yes")[boolean]
, aber es gibt keine Alternative, wenn Sie die Auswertung der beiden yes()
und no()
im folgenden vermeiden wollen:
yes() if [condition] else no()
, wenn die Variable definiert ist, und Sie möchten überprüfen, ob es Wert hat man nur a or b
kann
def test(myvar=None):
# shorter than: print myvar if myvar else "no Input"
print myvar or "no Input"
test()
test([])
test(False)
test('hello')
test(['Hello'])
test(True)
Wille Ausgang
no Input
no Input
no Input
hello
['Hello']
True
Eine saubere Art und Weise an der Kette mehr Operatoren:
f = lambda x,y: 'greater' if x > y else 'less' if y > x else 'equal'
array = [(0,0),(0,1),(1,0),(1,1)]
for a in array:
x, y = a[0], a[1]
print(f(x,y))
# Output is:
# equal,
# less,
# greater,
# equal