Se Python non ha un operatore condizionale ternario, è possibile simularne uno usando altri costrutti di linguaggio?
case [...] { when ... then ...} [ else ... ] end
un effetto simile ma non è affatto ternario.
Se Python non ha un operatore condizionale ternario, è possibile simularne uno usando altri costrutti di linguaggio?
case [...] { when ... then ...} [ else ... ] end
un effetto simile ma non è affatto ternario.
Risposte:
Sì, è stato aggiunto nella versione 2.5. La sintassi dell'espressione è:
a if condition else b
Prima condition
viene valutato, quindi esattamente uno di uno a
o b
viene valutato e restituito in base al valore booleano di condition
. Se viene condition
valutato True
, a
viene valutato e restituito ma b
viene ignorato, oppure quando b
viene valutato e restituito ma a
viene ignorato.
Ciò consente il corto circuito perché quando condition
viene a
valutato solo il valore vero e b
non viene valutato affatto, ma quando viene valutato condition
solo il valore falso b
e a
non viene valutato affatto.
Per esempio:
>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'
Nota che i condizionali sono un'espressione , non un'istruzione . Ciò significa che non è possibile utilizzare istruzioni di assegnazione pass
o altre istruzioni all'interno di un'espressione condizionale :
>>> pass if False else x = 3
File "<stdin>", line 1
pass if False else x = 3
^
SyntaxError: invalid syntax
Tuttavia, puoi utilizzare espressioni condizionali per assegnare una variabile in questo modo:
x = a if True else b
Pensa all'espressione condizionale come al passaggio tra due valori. È molto utile quando ci si trova in una situazione di "un valore o un altro", ma non fa molto altro.
Se è necessario utilizzare le istruzioni, è necessario utilizzare if
un'istruzione normale anziché un'espressione condizionale .
Tieni presente che è malvisto da alcuni pitonisti per diversi motivi:
condition ? a : b
operatore ternario rispetto a molti altri linguaggi (come C, C ++, Go, Perl, Ruby, Java, Javascript, ecc.), Il che può portare a bug quando le persone non hanno familiarità con Python " "comportamento sorprendente lo usano (possono invertire l'ordine degli argomenti).if
" possa essere davvero utile e rendere il tuo script più conciso, complica davvero il tuo codice)Se hai problemi a ricordare l'ordine, ricorda che quando leggi ad alta voce, dici (quasi) cosa intendi. Ad esempio, x = 4 if b > 8 else 9
viene letto ad alta voce come x will be 4 if b is greater than 8 otherwise 9
.
Documentazione ufficiale:
f(x) = |x| = x if x > 0 else -x
sembra molto naturale per i matematici. Puoi anche capirlo come nella maggior parte dei casi A, tranne quando C invece dovresti fare B invece ...
z = 3 + x if x < y else y
. Se x=2
e y=1
, ci si potrebbe aspettare che produca 4, ma in realtà produrrebbe 1. z = 3 + (x if x > y else y)
è l'uso corretto.
z = 3 + x if x < y else 3 + y
) o raggruppare il condizionale ( z = 3 + (x if x < y else y)
o z = (x if x < y else y) + 3
)
Puoi indicizzare in una tupla:
(falseValue, trueValue)[test]
test
deve restituire Vero o Falso .
Potrebbe essere più sicuro implementarlo sempre come:
(falseValue, trueValue)[test == True]
oppure puoi utilizzare il built-in bool()
per assicurare un valore booleano :
(falseValue, trueValue)[bool(<expression>)]
(lambda: print("a"), lambda: print("b"))[test==true]()
[]
s può essere un'espressione arbitraria. Inoltre, per sicurezza puoi testare esplicitamente la verità scrivendo [bool(<expression>)]
. La bool()
funzione è in uso dalla v2.2.1.
True
e False
come i tasti: {True:trueValue, False:falseValue}[test]
non so se questo sia meno efficiente, ma almeno evita il tutto Dibattito "elegante" vs. "brutto". Non c'è ambiguità che hai a che fare con un valore booleano piuttosto che un int.
Per le versioni precedenti alla 2.5, c'è il trucco:
[expression] and [on_true] or [on_false]
Può dare risultati errati quando on_true
ha un valore booleano falso. 1
Anche se ha il vantaggio di valutare le espressioni da sinistra a destra, il che è più chiaro secondo me.
<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
Dalla documentazione :
Le espressioni condizionali (a volte chiamate "operatori ternari") hanno la priorità più bassa di tutte le operazioni di Python.
L'espressione
x if C else y
valuta innanzitutto la condizione, C ( non x ); se C è vero, x viene valutato e il suo valore viene restituito; in caso contrario, viene valutato y e viene restituito il suo valore.Vedi PEP 308 per maggiori dettagli sulle espressioni condizionali.
Novità dalla versione 2.5.
Nel 2006 è stato aggiunto un operatore per un'espressione condizionale in Python come parte della proposta 308 di potenziamento di Python . La sua forma differisce dall'operatore comune ?:
ed è:
<expression1> if <condition> else <expression2>
che equivale a:
if <condition>: <expression1> else: <expression2>
Ecco un esempio:
result = x if a > b else y
Un'altra sintassi che può essere utilizzata (compatibile con le versioni precedenti alla 2.5):
result = (lambda:y, lambda:x)[a > b]()
dove gli operandi sono valutati pigramente .
Un altro modo è indicizzare una tupla (che non è coerente con l'operatore condizionale della maggior parte delle altre lingue):
result = (y, x)[a > b]
o dizionario esplicitamente costruito:
result = {True: x, False: y}[a > b]
Un altro metodo (meno affidabile), ma più semplice è l'uso and
e gli or
operatori:
result = (a > b) and x or y
tuttavia questo non funzionerebbe se x
lo fosse False
.
Una possibile soluzione alternativa è creare x
ed y
elenchi o tuple come di seguito:
result = ((a > b) and [x] or [y])[0]
o:
result = ((a > b) and (x,) or (y,))[0]
Se lavori con dizionari, invece di utilizzare un condizionale ternario, puoi trarre vantaggio get(key, default)
, ad esempio:
shell = os.environ.get('SHELL', "/bin/sh")
Fonte: ?: In Python su Wikipedia
result = {1: x, 0: y}[a > b]
è un'altra possibile variante ( True
e in False
realtà sono numeri interi con valori 1
e 0
)
Sfortunatamente, il
(falseValue, trueValue)[test]
la soluzione non ha un comportamento di corto circuito; quindi entrambi falseValue
e trueValue
vengono valutati indipendentemente dalla condizione. Questo potrebbe essere subottimale o addirittura buggy (cioè entrambi trueValue
e falseValue
potrebbero essere metodi e avere effetti collaterali).
Una soluzione a questo sarebbe
(lambda: falseValue, lambda: trueValue)[test]()
(esecuzione ritardata fino a quando il vincitore non è noto;)), ma introduce incoerenza tra oggetti richiamabili e non richiamabili. Inoltre, non risolve il caso quando si utilizzano le proprietà.
E così va la storia: scegliere tra le 3 soluzioni menzionate è un compromesso tra avere la funzionalità di corto circuito, usando almeno Зython 2.5 (IMHO non è più un problema) e non essere incline a errori " trueValue
-valuta-a-falsi" .
if else if
.
Qui provo solo a mostrare alcune importanti differenze ternary operator
tra un paio di linguaggi di programmazione.
Operatore ternario in Javascript
var a = true ? 1 : 0;
# 1
var b = false ? 1 : 0;
# 0
Operatore ternario in rubino
a = true ? 1 : 0
# 1
b = false ? 1 : 0
# 0
Operatore ternario alla Scala
val a = true ? 1 | 0
# 1
val b = false ? 1 | 0
# 0
Operatore ternario in programmazione R.
a <- if (TRUE) 1 else 0
# 1
b <- if (FALSE) 1 else 0
# 0
Operatore ternario in Python
a = 1 if True else 0
# 1
b = 1 if False else 0
# 0
Per Python 2.5 e versioni successive esiste una sintassi specifica:
[on_true] if [cond] else [on_false]
Nei vecchi Python un operatore ternario non è implementato ma è possibile simularlo.
cond and on_true or on_false
Anche se, c'è un potenziale problema, che se cond
restituisce True
e on_true
restituisce False
poi on_false
viene restituito al posto di on_true
. Se si desidera questo comportamento, il metodo è OK, altrimenti utilizzare questo:
{True: on_true, False: on_false}[cond is True] # is True, not == True
che può essere avvolto da:
def q(cond, on_true, on_false)
return {True: on_true, False: on_false}[cond is True]
e usato in questo modo:
q(cond, on_true, on_false)
È compatibile con tutte le versioni di Python.
q("blob", on_true, on_false)
restituisce on_false
, mentre on_true if cond else on_false
restituisce on_true
. Una soluzione alternativa è sostituire cond
con cond is not None
questi casi, anche se non è una soluzione perfetta.
bool(cond)
invece di cond is True
? Il primo verifica la veridicità di cond
, il secondo verifica l'uguaglianza puntatore con l' True
oggetto. Come sottolineato da @AndrewCecil, "blob"
è vero ma lo è is not True
.
[on_false, on_True][cond is True]
modo che l'espressione si accorcia.
Potresti trovare spesso
cond and on_true or on_false
ma questo porta a problemi quando on_true == 0
>>> x = 0
>>> print x == 0 and 0 or 1
1
>>> x = 1
>>> print x == 0 and 0 or 1
1
dove ti aspetteresti da un normale operatore ternario questo risultato
>>> x = 0
>>> print 0 if x == 0 else 1
0
>>> x = 1
>>> print 0 if x == 0 else 1
1
Python ha un operatore condizionale ternario?
Sì. Dal file di grammatica :
test: or_test ['if' or_test 'else' test] | lambdef
La parte di interesse è:
or_test ['if' or_test 'else' test]
Quindi, un'operazione condizionale ternaria ha la forma:
expression1 if expression2 else expression3
expression3
sarà valutato pigramente (cioè valutato solo se expression2
è falso in un contesto booleano). E a causa della definizione ricorsiva, puoi incatenarli indefinitamente (anche se può essere considerato un cattivo stile).
expression1 if expression2 else expression3 if expression4 else expression5 # and so on
Si noti che ogni if
deve essere seguito con un else
. Le persone che imparano la comprensione dell'elenco e le espressioni del generatore possono trovare questa una lezione difficile da imparare - quanto segue non funzionerà, poiché Python si aspetta una terza espressione per un altro:
[expression1 if expression2 for element in iterable]
# ^-- need an else here
che solleva a SyntaxError: invalid syntax
. Quindi quanto sopra è o un pezzo di logica incompleta (forse l'utente si aspetta una no-op in una falsa condizione) o ciò che si può intendere è usare expression2 come filtro - nota che quanto segue è Python legale:
[expression1 for element in iterable if expression2]
expression2
funziona come filtro per la comprensione dell'elenco e non è un operatore condizionale ternario.
Potresti trovare un po 'doloroso scrivere quanto segue:
expression1 if expression1 else expression2
expression1
dovrà essere valutato due volte con l'utilizzo di cui sopra. Può limitare la ridondanza se è semplicemente una variabile locale. Tuttavia, un linguaggio Pythonic comune e performante per questo caso d'uso è usare or
il comportamento di scorciatoia:
expression1 or expression2
che è equivalente in semantica. Si noti che alcune guide di stile possono limitare questo utilizzo per motivi di chiarezza: racchiude molto significato in una sintassi molto ridotta.
expression1 or expression2
essere simili e con gli stessi inconvenienti / positivi expression1 || expression2
di javascript
expressionN
per tutte le istanze sia coerente, potrebbe essere più semplice comprendere con la denominazione che distingue l'espressione condizionale del test dalle due espressioni di risultato; ad es result1 if condition else result2
. Ciò è particolarmente evidente quando nesting (alias concatenamento): result1 if condition1 else result2 if condition2 else result3
. Vedi quanto meglio si legge in questo modo?
Simulazione dell'operatore ternario del pitone.
Per esempio
a, b, x, y = 1, 2, 'a greather than b', 'b greater than a'
result = (lambda:y, lambda:x)[a > b]()
produzione:
'b greater than a'
result = (y, x)[a < b]
Perché usi la lambda
funzione ?
L'operatore condizionale ternario consente semplicemente di testare una condizione in una singola riga sostituendo l'ifine multilinea rendendo compatto il codice.
[on_true] if [espressione] else [on_false]
# 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
# 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
# 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")
L'approccio sopra può essere scritto come:
# 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
if-else
realtà non è una riscrittura dell'operatore ternario e produrrà output diversi per selezionare i valori di aeb (in particolare se uno è un tipo che implementa un __ne__
metodo strano ).
Puoi farlo :-
[condition] and [expression_1] or [expression_2] ;
Esempio:-
print(number%2 and "odd" or "even")
Questo stampa "dispari" se il numero è dispari o "pari" se il numero è pari.
Nota :- 0, None, False, emptylist, emptyString viene valutato come False. E tutti i dati diversi da 0 vengono valutati su True.
se la condizione [condizione] diventa "Vero", verrà valutata expression_1 ma non expression_2. Se noi "e" qualcosa con 0 (zero), il risultato sarà sempre fasle. Quindi nell'istruzione seguente,
0 and exp
L'espressione exp non verrà valutata affatto poiché "e" con 0 verranno sempre valutati a zero e non è necessario valutare l'espressione. Ecco come funziona il compilatore stesso, in tutte le lingue.
In
1 or exp
l'espressione exp non verrà valutata affatto poiché "o" con 1 sarà sempre 1. Quindi non si preoccuperà di valutare l'espressione exp poiché il risultato sarà comunque 1. (metodi di ottimizzazione del compilatore).
Ma in caso di
True and exp1 or exp2
La seconda espressione exp2 non verrà valutata da allora True and exp1
sarebbe vera quando exp1 non sarebbe falsa.
Allo stesso modo in
False and exp1 or exp2
L'espressione exp1 non verrà valutata poiché False equivale a scrivere 0 e fare "e" con 0 sarebbe 0 stesso ma dopo che exp1 è stato usato "o", valuterà l'espressione exp2 dopo "o".
Nota: - Questo tipo di diramazione che utilizza "o" e "e" può essere utilizzato solo quando expression_1 non ha un valore Truth di False (o 0 o None o emptylist [] o emptystring ''.) Poiché se expression_1 diventa Falso, quindi expression_2 verrà valutato a causa della presenza "o" tra exp_1 ed exp_2.
Nel caso in cui desideri ancora farlo funzionare per tutti i casi, indipendentemente dai valori di verità exp_1 ed exp_2, procedi come segue: -
[condition] and ([expression_1] or 1) or [expression_2] ;
x = [condition] and ([expression_1] or 1) or [expression_2]
e expression_1
FALSE, x
sarà 1
, no expression_1
. Usa la risposta accettata.
Più un suggerimento che una risposta (non è necessario ripetere l'ovvio per la prima volta), ma a volte lo uso come scorciatoia da linea in tali costrutti:
if conditionX:
print('yes')
else:
print('nah')
, diventa:
print('yes') if conditionX else print('nah')
Alcuni (molti :) potrebbero non giudicarli come non ritmici (persino, rubini-ish :), ma personalmente lo trovo più naturale, cioè come lo esprimeresti normalmente, più un po 'più visivamente accattivante in grandi blocchi di codice.
print( 'yes' if conditionX else 'nah' )
la tua risposta. :-)
print()
in entrambi i casi - e sembra un po 'più pitonico, devo ammetterlo :) Ma cosa succede se le espressioni / funzioni non sono le stesse - come print('yes') if conditionX else True
- per ottenere l' print()
unico in veritàconditionX
print('yes') if conditionX else print('nah')
all'osservazione di Frederick99, un altro motivo da evitare è che fornisce un SyntaxError in Python2.
print "yes"
, mentre in Python 3 è una funzione - print("yes")
. Ciò può essere risolto usandolo come una dichiarazione, o meglio - from future import print_function
.
Una delle alternative all'espressione condizionale di Python
"yes" if boolean else "no"
è il seguente:
{True:"yes", False:"no"}[boolean]
che ha la seguente estensione piacevole:
{True:"yes", False:"no", None:"maybe"}[boolean_or_none]
L'alternativa più breve rimane:
("no", "yes")[boolean]
ma non c'è alternativa a
yes() if boolean else no()
se si desidera evitare la valutazione di yes()
e no()
, perché in
(no(), yes())[boolean] # bad
entrambi no()
e yes()
vengono valutati.
Molti linguaggi di programmazione derivati di C
solito hanno la seguente sintassi dell'operatore condizionale ternario:
<condition> ? <expression1> : <expression2>
In un primo momento, il
Python
B enevolent D ictator F o L IFE (intendo Guido van Rossum, ovviamente) respinto (come lo stile non Pythonic), dal momento che è molto difficile da capire per le persone non utilizzati perC
la lingua. Inoltre, il segno dei due punti:
ha già molti usi inPython
. Dopo che PEP 308 è stato approvato, haPython
finalmente ricevuto la sua espressione condizionale di collegamento (quello che usiamo ora):
<expression1> if <condition> else <expression2>
Quindi, in primo luogo valuta la condizione. Se restituisce True
, verrà valutato expression1 per fornire il risultato, altrimenti verrà valutato expression2 . A causa della meccanica di valutazione pigra, verrà eseguita solo un'espressione.
Ecco alcuni esempi (le condizioni saranno valutate da sinistra a destra):
pressure = 10
print('High' if pressure < 20 else 'Critical')
# Result is 'High'
Gli operatori ternari possono essere concatenati in serie:
pressure = 5
print('Normal' if pressure < 10 else 'High' if pressure < 20 else 'Critical')
# Result is 'Normal'
Quello seguente è uguale al precedente:
pressure = 5
if pressure < 20:
if pressure < 10:
print('Normal')
else:
print('High')
else:
print('Critical')
# Result is 'Normal'
Spero che sia di aiuto.
Come già risposto, sì, c'è un operatore ternario in Python:
<expression 1> if <condition> else <expression 2>
Informazioni aggiuntive:
Se <expression 1>
è la condizione è possibile utilizzare la valutazione Short-cirquit :
a = True
b = False
# Instead of this:
x = a if a else b
# You could use Short-cirquit evaluation:
x = a or b
PS: Naturalmente, una valutazione del cortocircuito non è un operatore ternario, ma spesso il ternario viene utilizzato nei casi in cui il corto circuito sarebbe sufficiente.
short-circuit
valutazione.
SÌ, Python ha un operatore ternario, ecco la sintassi e un codice di esempio per dimostrare lo stesso :)
#[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")
print
non è davvero una buona scelta, in quanto ciò darà un SyntaxError in Python2.
Python ha una forma ternaria per gli incarichi; tuttavia potrebbe esserci anche una forma più breve di cui le persone dovrebbero essere consapevoli.
È molto comune dover assegnare a una variabile un valore o un altro a seconda di una condizione.
>>> li1 = None
>>> li2 = [1, 2, 3]
>>>
>>> if li1:
... a = li1
... else:
... a = li2
...
>>> a
[1, 2, 3]
^ Questa è la forma lunga per svolgere tali incarichi.
Di seguito è la forma ternaria. Ma questo non è il modo più conciso - vedi l'ultimo esempio.
>>> a = li1 if li1 else li2
>>>
>>> a
[1, 2, 3]
>>>
Con Python, puoi semplicemente utilizzarlo or
per compiti alternativi.
>>> a = li1 or li2
>>>
>>> a
[1, 2, 3]
>>>
Quanto sopra funziona poiché li1
è None
e l'interp lo considera Falso nelle espressioni logiche. L'interp si sposta quindi e valuta la seconda espressione, che non è None
e non è un elenco vuoto, quindi viene assegnata a.
Questo funziona anche con liste vuote. Ad esempio, se si desidera assegnare a
qualsiasi elenco contenga elementi.
>>> li1 = []
>>> li2 = [1, 2, 3]
>>>
>>> a = li1 or li2
>>>
>>> a
[1, 2, 3]
>>>
Sapendo questo, puoi semplicemente assegnare tali incarichi ogni volta che li incontri. Questo funziona anche con stringhe e altri iterabili. È possibile assegnare a
qualsiasi stringa non vuota.
>>> s1 = ''
>>> s2 = 'hello world'
>>>
>>> a = s1 or s2
>>>
>>> a
'hello world'
>>>
Mi è sempre piaciuta la sintassi ternaria C, ma Python fa un passo avanti!
Capisco che alcuni potrebbero dire che questa non è una buona scelta stilistica perché si basa su meccanismi che non sono immediatamente evidenti a tutti gli sviluppatori. Personalmente non sono d'accordo con questo punto di vista. Python è un linguaggio ricco di sintassi con molti trucchi idiomatici che non sono immediatamente evidenti al dabler. Ma più impari e comprendi i meccanismi del sistema sottostante, più lo apprezzi.
Altre risposte parlano correttamente dell'operatore ternario Python. Vorrei integrare citando uno scenario per il quale viene spesso utilizzato l'operatore ternario ma per il quale esiste un linguaggio migliore. Questo è lo scenario di utilizzo di un valore predefinito.
Supponiamo di voler utilizzare option_value
un valore predefinito se non è impostato:
run_algorithm(option_value if option_value is not None else 10)
o semplicemente
run_algorithm(option_value if option_value else 10)
Tuttavia, una soluzione sempre migliore è semplicemente scrivere
run_algorithm(option_value or 10)
se la variabile è definita e si desidera verificare se ha valore, si può semplicemente a or b
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)
uscirà
no Input
no Input
no Input
hello
['Hello']
True
x if x else y
, ma non x if z else y
.
Un modo pulito per concatenare più operatori:
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
Trovo ingombrante la sintassi di Python predefinita val = a if cond else b
, quindi a volte lo faccio:
iif = lambda (cond, a, b): a if cond else b
# so I can then use it like:
val = iif(cond, a, b)
Certo, ha il rovescio della medaglia di valutare sempre entrambi i lati (aeb), ma la sintassi è molto più chiara per me
val = a if cond else b
dichiarazione più semplice .
is_spacial=True if gender = "Female" else (True if age >= 65 else False)
**
può essere nidificato secondo le tue necessità. buona fortuna
**