Se Python non ha un operatore condizionale ternario, è possibile simularne uno usando altri costrutti di linguaggio?
case [...] { when ... then ...} [ else ... ] endun 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 ... ] endun effetto simile ma non è affatto ternario.
Risposte:
Sì, è stato aggiunto nella versione 2.5. La sintassi dell'espressione è:
a if condition else b
Prima conditionviene valutato, quindi esattamente uno di uno ao bviene valutato e restituito in base al valore booleano di condition. Se viene conditionvalutato True, aviene valutato e restituito ma bviene ignorato, oppure quando bviene valutato e restituito ma aviene ignorato.
Ciò consente il corto circuito perché quando conditionviene avalutato solo il valore vero e bnon viene valutato affatto, ma quando viene valutato conditionsolo il valore falso be anon 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 passo 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 : boperatore 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 9viene 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 -xsembra 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=2e 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]
testdeve 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.
Truee Falsecome 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 yvaluta 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 ande gli oroperatori:
result = (a > b) and x or y
tuttavia questo non funzionerebbe se xlo fosse False.
Una possibile soluzione alternativa è creare xed yelenchi 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 ( Truee in Falserealtà sono numeri interi con valori 1e 0)
Sfortunatamente, il
(falseValue, trueValue)[test]
la soluzione non ha un comportamento di corto circuito; quindi entrambi falseValuee trueValuevengono valutati indipendentemente dalla condizione. Questo potrebbe essere subottimale o addirittura buggy (cioè entrambi trueValuee falseValuepotrebbero 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 operatortra 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 condrestituisce Truee on_truerestituisce Falsepoi on_falseviene 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_falserestituisce on_true. Una soluzione alternativa è sostituire condcon cond is not Nonequesti 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' Trueoggetto. 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
expression3sarà 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 ifdeve 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]
expression2funziona 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
expression1dovrà 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 oril 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 expression2essere simili e con gli stessi inconvenienti / positivi expression1 || expression2di javascript
expressionNper 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 lambdafunzione ?
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-elserealtà 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_1FALSE, xsarà 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 Csolito hanno la seguente sintassi dell'operatore condizionale ternario:
<condition> ? <expression1> : <expression2>
In un primo momento, il
PythonB 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 perCla lingua. Inoltre, il segno dei due punti:ha già molti usi inPython. Dopo che PEP 308 è stato approvato, haPythonfinalmente 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-circuitvalutazione.
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")
printnon è 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 orper compiti alternativi.
>>> a = li1 or li2
>>>
>>> a
[1, 2, 3]
>>>
Quanto sopra funziona poiché li1è Nonee l'interp lo considera Falso nelle espressioni logiche. L'interp si sposta quindi e valuta la seconda espressione, che non è Nonee non è un elenco vuoto, quindi viene assegnata a.
Questo funziona anche con liste vuote. Ad esempio, se si desidera assegnare aqualsiasi 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 aqualsiasi 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_valueun 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 bdichiarazione più semplice .
is_spacial=True if gender = "Female" else (True if age >= 65 else False)
**
può essere nidificato secondo le tue necessità. buona fortuna
**