Eine if-elif-else-Anweisung in eine Zeile setzen?

123

Ich habe die folgenden Links gelesen, aber meine Frage wird nicht beantwortet.
Hat Python einen ternären bedingten Operator? (Bei der Frage geht es darum, die if-else-Anweisung auf eine Zeile zu reduzieren.)

Gibt es eine einfachere Möglichkeit, eine if-elif-else-Anweisung so zu schreiben, dass sie in eine Zeile passt?
Beispielsweise,

if expression1:
   statement1
elif expression2:
   statement2
else:
   statement3

Oder ein Beispiel aus der Praxis:

if i > 100:
    x = 2
elif i < 100:
    x = 1
else:
    x = 0

Ich habe nur das Gefühl, wenn das obige Beispiel folgendermaßen geschrieben werden könnte, könnte es prägnanter aussehen.

x=2 if i>100 elif i<100 1 else 0 [WRONG]
Matt Elson
quelle

Antworten:

183

Nein, es ist weder möglich (zumindest nicht mit willkürlichen Aussagen) noch wünschenswert. Wenn Sie alles in eine Zeile einfügen, wird dies höchstwahrscheinlich gegen PEP-8 verstoßen, wenn die Zeilen nicht länger als 80 Zeichen sein dürfen.

Es ist auch gegen das Zen von Python: "Lesbarkeit zählt". (Geben Sie import thisan der Python-Eingabeaufforderung ein, um das Ganze zu lesen.)

Sie können einen ternären Ausdruck in Python verwenden, jedoch nur für Ausdrücke, nicht für Anweisungen:

>>> a = "Hello" if foo() else "Goodbye"

Bearbeiten:

Ihre überarbeitete Frage zeigt nun, dass die drei Anweisungen bis auf den zugewiesenen Wert identisch sind. In diesem Fall funktioniert ein verketteter ternärer Operator, aber ich denke immer noch, dass er weniger lesbar ist:

>>> i=100
>>> a = 1 if i<100 else 2 if i>100 else 0
>>> a
0
>>> i=101
>>> a = 1 if i<100 else 2 if i>100 else 0
>>> a
2
>>> i=99
>>> a = 1 if i<100 else 2 if i>100 else 0
>>> a
1
Tim Pietzcker
quelle
Warum hat der zweite Ausdruck nicht 0 zurückgegeben? Ich
bin
6
@AstralWolf: Vielen Dank! Dies veranschaulicht perfekt den Punkt, den ich ansprechen wollte - ein verketteter ternärer Ausdruck ist möglich, aber weniger lesbar und offensichtlich leicht zu missverstehen.
Tim Pietzcker
1
Wenn Sie a = 1 if i < 100 else (2 if i > 100 else 0)möchten, dass es besser lesbar ist, können Sie es wie folgt umklammern : (Ungetestet, aber ich denke, es sollte funktionieren)
Zac
@ TimPietzcker Wie würden Sie den Unterschied zwischen Ausdrücken und Anweisungen beschreiben?
AsheKetchum
62

Wenn Sie nur unterschiedliche Ausdrücke für unterschiedliche Fälle benötigen, funktioniert dies möglicherweise für Sie:

expr1 if condition1 else expr2 if condition2 else expr

Beispielsweise:

a = "neg" if b<0 else "pos" if b>0 else "zero"
Lycha
quelle
1
"pos"ist keine Aussage, es ist ein Ausdruck.
Tim Pietzcker
@ TimPietzcker Danke, ich habe den Beitrag aktualisiert, um genauer zu sein.
Lycha
20

Verschachteln Sie einfach eine andere if-Klausel in der else-Anweisung. Aber das macht es nicht schöner.

>>> x=5
>>> x if x>0 else ("zero" if x==0 else "invalid value")
5
>>> x = 0
>>> x if x>0 else ("zero" if x==0 else "invalid value")
'zero'
>>> x = -1
>>> x if x>0 else ("zero" if x==0 else "invalid value")
'invalid value'
David Lai
quelle
1
Für mich ist dies viel besser lesbar als die akzeptierte Antwort, da die Struktur und das Konzept des ersten Satzes beibehalten werden. nur subjektive Angelegenheit.
Ezarate11
11

Trotz einiger anderer Antworten: JA, es ist möglich :

if expression1:
   statement1
elif expression2:
   statement2
else:
   statement3

übersetzt in den folgenden einen Liner:

statement1 if expression1 else (statement2 if expression2 else statement3)

Tatsächlich können Sie diese bis ins Unendliche verschachteln. Genießen ;)

gustavz
quelle
Wie wäre es mit der Zeit? Was ich vermute, werden diese Muti-Loops viel zeitaufwändiger sein. Kann es also eine Alternative zu verschachtelten Schleifen geben, um die Verbrauchsgeschwindigkeit zu erhöhen?
loveR
hi @loveR, dies ist keine Schleife, es ist nur eine verschachtelte if else-Anweisung und daher von vernachlässigbarer Zeit
gustavz
7

Optional können Sie die getMethode a verwenden dict:

x = {i<100: -1, -10<=i<=10: 0, i>100: 1}.get(True, 2)

Sie benötigen die getMethode nicht, wenn garantiert ist, dass einer der Schlüssel Folgendes auswertet True:

x = {i<0: -1, i==0: 0, i>0: 1}[True]

Höchstens sollte einer der Schlüssel idealerweise auswerten True. Wenn mehr als ein Schlüssel ausgewertet wird, Truekönnen die Ergebnisse unvorhersehbar erscheinen.

Shane
quelle
4
if i > 100:
    x = 2
elif i < 100:
    x = 1
else:
    x = 0

Wenn Sie den oben genannten Code in einer Zeile verwenden möchten, können Sie Folgendes verwenden:

x = 2 if i > 100 else 1 if i < 100 else 0

Dabei wird x 2 zugewiesen, wenn i> 100, 1, wenn i <100 und 0, wenn i = 100

Roshanpoudel
quelle
3

Es hängt auch von der Art Ihrer Ausdrücke ab. Der allgemeine Rat zu den anderen Antworten "Nicht tun" gilt für generische Aussagen und generische Ausdrücke.

Wenn Sie jedoch nur eine "Versand" -Tabelle benötigen, z. B. das Aufrufen einer anderen Funktion, abhängig vom Wert einer bestimmten Option, können Sie die aufzurufenden Funktionen in ein Wörterbuch einfügen.

Etwas wie:

def save(): 
   ...
def edit():
   ...
options = {"save": save, "edit": edit, "remove": lambda : "Not Implemented"}

option = get_input()
result = options[option]()

Anstelle eines Wenn-Sonst:

if option=="save":
    save()
...
jsbueno
quelle
2

Die Leute haben bereits ternäre Ausdrücke erwähnt. Manchmal ist es mit einer einfachen bedingten Zuweisung als Beispiel möglich, einen mathematischen Ausdruck zu verwenden, um die bedingte Zuweisung durchzuführen. Dies macht Ihren Code möglicherweise nicht sehr lesbar, bringt ihn jedoch in eine ziemlich kurze Zeile. Ihr Beispiel könnte folgendermaßen geschrieben werden:

x = 2*(i>100) | 1*(i<100)

Die Vergleiche wären wahr oder falsch, und wenn mit Zahlen multipliziert würde, wäre dies entweder 1 oder 0. Man könnte ein + anstelle eines | verwenden mitten drin.

Ant6n
quelle
1

Der ternäre Operator ist der beste Weg zu einem präzisen Ausdruck. Die Syntax lautet variable = value_1 if condition else value_2. In Ihrem Beispiel müssen Sie den ternären Operator also zweimal anwenden:

i = 23 # set any value for i
x = 2 if i > 100 else 1 if i < 100 else 0
Yoelvis
quelle
0

Sie können verschachtelte ternäre if-Anweisungen verwenden.

# if-else ternary construct
country_code = 'USA'
is_USA = True if country_code == 'USA' else False
print('is_USA:', is_USA)

# if-elif-else ternary construct
# Create function to avoid repeating code.
def get_age_category_name(age):
    age_category_name = 'Young' if age <= 40 else ('Middle Aged' if age > 40 and age <= 65 else 'Senior')
    return age_category_name

print(get_age_category_name(25))
print(get_age_category_name(50))
print(get_age_category_name(75))
k0L1081
quelle