7948 Stimmen

Verfügt Python über einen ternären bedingten Operator?

Wenn Python keine ternärer Konditionaloperator Ist es möglich, andere Sprachkonstrukte zu verwenden, um eine solche zu simulieren?

4 Stimmen

Obwohl Pythons, die älter als 2.5 sind, langsam der Vergangenheit angehören, gibt es hier eine Liste alter ternärer Operator-Tricks aus der Zeit vor 2.5: "Python Idioms", Suche nach dem Text 'Conditional expression' (Bedingter Ausdruck) . Wikipedia ist auch sehr hilfreich :-)

212 Stimmen

In der offiziellen Dokumentation zu Python 3.0, auf die in einem Kommentar oben verwiesen wird, wird dies als "conditional_expressions" bezeichnet und ist sehr kryptisch definiert. Diese Dokumentation enthält nicht einmal den Begriff "ternär", so dass man nur schwerlich über Google danach suchen kann, wenn man nicht genau weiß, wonach man suchen muss. Die Version 2 Dokumentation ist etwas hilfreicher und enthält einen Link zu "PEP 308" die eine Menge interessanter historischer Zusammenhänge zu dieser Frage enthält.

48 Stimmen

"ternär" (mit drei Eingängen) ist eine Folgeeigenschaft dieser Aufteilung, keine definierende Eigenschaft des Konzepts. z.B.: SQL hat case [...] { when ... then ...} [ else ... ] end für eine ähnliche Wirkung, aber keineswegs ternär.

55voto

Verfügt Python über einen ternären bedingten Operator?

Ja. Von der Grammatikdatei :

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

Dieser Teil ist von Interesse:

or_test ['if' or_test 'else' test]

Eine ternäre bedingte Operation hat also die Form:

expression1 if expression2 else expression3

expression3 faul ausgewertet (d. h. nur ausgewertet, wenn expression2 in einem booleschen Kontext falsch ist). Und aufgrund der rekursiven Definition können Sie sie unbegrenzt verketten (obwohl dies als schlechter Stil angesehen werden kann).

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

Ein Hinweis zur Verwendung:

Beachten Sie, dass jeder if muss mit einer else . Für Personen, die Listenverstehenssätze und Generatorausdrücke lernen, kann dies eine schwierige Lektion sein - 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

die eine SyntaxError: invalid syntax . Das obige Beispiel ist also entweder ein unvollständiges Stück Logik (vielleicht erwartet der Benutzer ein no-op in der falschen Bedingung) oder es ist beabsichtigt, die expression2 als Filter - 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 pas ein ternärer bedingter Operator.

Alternative Syntax für einen engeren Fall:

Sie werden es vielleicht etwas schmerzhaft finden, das Folgende zu schreiben:

expression1 if expression1 else expression2

expression1 muss bei der obigen Verwendung zweimal ausgewertet werden. Es kann die Redundanz begrenzen, wenn es einfach eine lokale Variable ist. Ein gängiges und leistungsfähiges Pythonic Idiom für diesen Anwendungsfall ist jedoch die Verwendung von or Verhalten der Abkürzungen:

expression1 or expression2

was semantisch gleichwertig ist. Beachten Sie, dass einige Styleguides diese Verwendung aus Gründen der Klarheit einschränken können - sie verpackt eine Menge Bedeutung in sehr wenig Syntax.

0 Stimmen

@AaronHall Obwohl Ihre Verwendung von metasyntaktischen expressionN für alle Instanzen konsistent ist, könnte es mit einer Benennung, die den bedingten Testausdruck von den beiden Ergebnisausdrücken unterscheidet, einfacher zu verstehen sein; z. B, result1 if condition else result2 . Dies wird besonders bei der Verschachtelung (aka Verkettung) deutlich: result1 if condition1 else result2 if condition2 else result3 . Sehen Sie, wie viel besser sich das so liest?

1 Stimmen

@tchrist danke für die Kritik - wenn Sie sich den Änderungsverlauf ansehen, hat dieser Beitrag derzeit zwei Überarbeitungen. Die meisten meiner anderen Antworten, vor allem die oberen, sind immer wieder überarbeitet worden. Diese Antwort bekommt nie meine Aufmerksamkeit, weil der Community-Wiki-Status mir keine Anerkennung für den Inhalt gibt und ich daher nie irgendwelche Stimmen dazu sehe. Da ich im Moment nicht wirklich Zeit für eine Bearbeitung habe, weiß Frosch, wann ich in Zukunft wieder darauf aufmerksam werde. Wie ich sehe, haben Sie die oberste Antwort bearbeitet, Sie können also gerne mein Material aus diesem Beitrag in diesem Beitrag ausleihen/zitieren (und mich zitieren, wenn es angebracht ist!)

1 Stimmen

expression1 or expression2 ähnlich und mit den gleichen Nachteilen/Positiven wie expression1 || expression2 in Javascript

45voto

Walter Tross Punkte 11394

Eine der Alternativen zu Pythons bedingter Ausdruck

"yes" if boolean else "no"

ist die folgende:

{True:"yes", False:"no"}[boolean]

die die folgende schöne Erweiterung hat:

{True:"yes", False:"no", None:"maybe"}[boolean_or_none]

Es bleibt die kürzeste Alternative:

("no", "yes")[boolean]

aber es gibt keine Alternative zu

yes() if boolean else no()

wenn Sie die Auswertung von yes() und no() denn in

(no(), yes())[boolean]  # bad

beide no() et yes() bewertet werden.

0 Stimmen

Alternativ: (no, yes)[boolean]()

35voto

Frank Punkte 1523

Wie bereits beantwortet, ja, es gibt einen ternären Operator in Python:

<expression 1> if <condition> else <expression 2>

In vielen Fällen <expression 1> wird auch als boolesche Auswertung verwendet <condition> . Dann können Sie Kurzschlussauswertung .

a = 0
b = 1

# Instead of this:
x = a if a else b
# Evaluates as 'a if bool(a) else b'

# You could use short-circuit evaluation:
x = a or b

Ein großer Vorteil der Kurzschlussauswertung ist die Möglichkeit, mehr als zwei Ausdrücke zu verketten:

x = a or b or c or d or e

Bei der Arbeit mit Funktionen ist es im Detail etwas anders:

# Evaluating functions:
def foo(x):
    print('foo executed')
    return x

def bar(y):
    print('bar executed')
    return y

def blubb(z):
    print('blubb executed')
    return z

# Ternary Operator expression 1 equals to False
print(foo(0) if foo(0) else bar(1))
''' foo and bar are executed once
foo executed
bar executed
1
'''

# Ternary Operator expression 1 equals to True
print(foo(2) if foo(2) else bar(3))
''' foo is executed twice!
foo executed
foo executed
2
'''

# Short-circuit evaluation second equals to True
print(foo(0) or bar(1) or blubb(2))
''' blubb is not executed
foo executed
bar executed
1
'''

# Short-circuit evaluation third equals to True
print(foo(0) or bar(0) or blubb(2))
'''
foo executed
bar executed
blubb executed
2
'''

# Short-circuit evaluation all equal to False
print(foo(0) or bar(0) or blubb(0))
''' Result is 0 (from blubb(0)) because no value equals to True
foo executed
bar executed
blubb executed
0
'''

PS: Natürlich ist eine Kurzschlussauswertung kein ternärer Operator, aber oft wird der ternäre Operator in Fällen verwendet, in denen der Kurzschluss ausreichen würde. Er hat eine bessere Lesbarkeit und kann verkettet werden.

33voto

Sasikiran Vaddi Punkte 1559

Simulation des ternären Python-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'

1 Stimmen

Warum nicht einfach result = (y, x)[a < b] Warum verwenden Sie lambda Funktion ?

6 Stimmen

@GrijeshChauhan Denn bei "kompatiblen" Ausdrücken, die z. B. einen Funktionsaufruf usw. enthalten, würde dies in beiden Fällen ausgeführt. Dies ist möglicherweise nicht erwünscht.

2 Stimmen

Die Verwendung von lambda Funktionen sind ein Overkill für diese Frage

31voto

David Chung Punkte 61

Vinko Vrsalovic's Antwort ist gut genug. Da ist nur noch eine Sache:

Beachten Sie, dass Konditionale ein Ausdruck , nicht ein Anweisung . Das heißt, Sie können keine Zuweisungsanweisungen oder pass oder andere Aussagen innerhalb einer bedingten Ausdruck

Walross-Operator in Python 3.8

Nachdem die Walross-Betreiber in Python 3.8 eingeführt wurde, hat sich etwas geändert.

(a := 3) if True else (b := 5)

gibt a = 3 et b is not defined ,

(a := 3) if False else (b := 5)

gibt a is not defined et b = 5 und

c = (a := 3) if False else (b := 5)

gibt c = 5 , a is not defined et b = 5 .

Auch wenn dies hässlich sein mag, Zuweisungen kann durchgeführt werden innerhalb bedingte Ausdrücke nach Python 3.8. Wie auch immer, es ist immer noch besser, normale if Anweisung stattdessen in diesem Fall.

0 Stimmen

Im ersten Beispiel: (a := 3) if True else (b := 5) Eigentlich ist es ein überflüssiger erster Walross-Operator. Das wird reichen: a = 3 if True else (b := 5)

2 Stimmen

@AndrewAnderson Nein, es ist nicht überflüssig. Sie sollten sowohl das erste als auch das zweite Beispiel vergleichen. Sie können sie kombinieren und dies berücksichtigen: (a := 3) if x else (b := 5) erhalten Sie immer entweder a o b zugewiesen, nicht beides. Beachten Sie jedoch a = 3 if x else (b := 5) wenn x == False erhalten Sie a = 5 y b = 5 wo sie beide zugeordnet sind.

0 Stimmen

Ja, das ist richtig :). Ich habe dies nur für x=True Fall, der natürlich begrenzt ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X