Mettere un'istruzione if-elif-else su una riga?


124

Ho letto i link sottostanti, ma non risolve la mia domanda.
Python ha un operatore condizionale ternario? (la domanda riguarda la condensazione dell'istruzione if-else su una riga)

C'è un modo più semplice per scrivere un'istruzione if-elif-else in modo che stia su una riga?
Per esempio,

if expression1:
   statement1
elif expression2:
   statement2
else:
   statement3

O un esempio del mondo reale:

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

Sento solo che se l'esempio sopra potesse essere scritto nel modo seguente, potrebbe sembrare più conciso.

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

Risposte:


184

No, non è possibile (almeno non con dichiarazioni arbitrarie), né è desiderabile. Adattare tutto su una riga molto probabilmente violerebbe PEP-8 dove è obbligatorio che le righe non superino gli 80 caratteri di lunghezza.

È anche contro lo Zen di Python: "La leggibilità conta". (Digita import thisal prompt di Python per leggere l'intera cosa).

È possibile utilizzare un'espressione ternaria in Python, ma solo per le espressioni, non per le dichiarazioni:

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

Modificare:

La tua domanda rivista ora mostra che le tre affermazioni sono identiche ad eccezione del valore assegnato. In tal caso, un operatore ternario concatenato funziona, ma penso comunque che sia meno leggibile:

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

Perché la seconda espressione non ha restituito 0? i è superiore a 100
AstralWolf

6
@AstralWolf: grazie mille! Questo illustra perfettamente il punto che stavo cercando di sottolineare: un'espressione ternaria incatenata è possibile ma meno leggibile e ovviamente facile da fraintendere.
Tim Pietzcker

1
Se hai bisogno che sia più leggibile, potresti mettere delle parentesi attorno ad esso, in questo modo: a = 1 if i < 100 else (2 if i > 100 else 0)(Non testato, ma penso che dovrebbe funzionare)
Zac

@TimPietzcker come descriveresti la differenza tra espressioni e affermazioni?
AsheKetchum

62

Se hai bisogno solo di espressioni diverse per casi diversi, questo potrebbe funzionare per te:

expr1 if condition1 else expr2 if condition2 else expr

Per esempio:

a = "neg" if b<0 else "pos" if b>0 else "zero"

1
"pos"non è un'affermazione, è un'espressione.
Tim Pietzcker

@TimPietzcker Grazie, ho aggiornato il post per essere più accurato.
Lycha

20

Basta annidare un'altra clausola if nell'istruzione else. Ma questo non lo fa sembrare più carino.

>>> 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'

1
Per me, questo è molto più leggibile della risposta accettata perché mantiene la struttura e il concetto della prima clausola; solo questione soggettiva.
Ezarate 11

12

Nonostante alcune altre risposte: SI è possibile :

if expression1:
   statement1
elif expression2:
   statement2
else:
   statement3

si traduce nella seguente riga:

statement1 if expression1 else (statement2 if expression2 else statement3)

infatti puoi annidarli fino all'infinito. Godere ;)


che ne dici del tempo impiegato? quello che suppongo, questi muti-loop richiederanno molto più tempo. quindi può esserci un'alternativa ai cicli annidati, per una migliore velocità di consumo.
loveR

ciao @loveR, questo non è un loop, è solo un'istruzione if else annidata, e quindi di tempo trascurabile
gustavz

7

Facoltativamente, puoi effettivamente utilizzare il getmetodo di dict:

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

Non è necessario il getmetodo se è garantito che una delle chiavi valuti True:

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

Al massimo una delle chiavi dovrebbe idealmente valutare True. Se viene valutata più di una chiave True, i risultati potrebbero sembrare imprevedibili.



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

Se vuoi usare il codice sopra menzionato in una riga, puoi usare quanto segue:

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

In tal modo, x verrà assegnato 2 se i> 100, 1 se i <100 e 0 se i = 100


3

Dipende anche dalla natura delle tue espressioni. Il consiglio generale sulle altre risposte di "non farlo" è abbastanza valido per affermazioni generiche ed espressioni generiche.

Ma se tutto ciò di cui hai bisogno è una tabella di "invio", come chiamare una funzione diversa a seconda del valore di una data opzione, puoi inserire le funzioni da chiamare all'interno di un dizionario.

Qualcosa di simile a:

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

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

Invece di un if-else:

if option=="save":
    save()
...

2

Le persone hanno già menzionato le espressioni ternarie. A volte con un semplice assegnamento condizionale come esempio, è possibile utilizzare un'espressione matematica per eseguire l'assegnazione condizionale. Questo potrebbe non rendere il tuo codice molto leggibile, ma lo ottiene su una riga abbastanza breve. Il tuo esempio potrebbe essere scritto così:

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

I confronti sarebbero Vero o Falso, e quando si moltiplicano i numeri sarebbero quindi 1 o 0. Si potrebbe usare un + invece di un | nel mezzo.


1

L' operatore ternario è il modo migliore per un'espressione concisa. La sintassi è variable = value_1 if condition else value_2. Quindi, per il tuo esempio, devi applicare l'operatore ternario due volte:

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

0

Puoi usare istruzioni if ​​ternarie annidate.

# 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))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.