Si Python no tiene un operador condicional ternario, ¿es posible simular uno usando otras construcciones de lenguaje?
case [...] { when ... then ...} [ else ... ] end
un efecto similar pero no es en absoluto ternario.
Si Python no tiene un operador condicional ternario, ¿es posible simular uno usando otras construcciones de lenguaje?
case [...] { when ... then ...} [ else ... ] end
un efecto similar pero no es en absoluto ternario.
Respuestas:
Sí, se agregó en la versión 2.5. La sintaxis de la expresión es:
a if condition else b
En primer lugar condition
se evalúa, a continuación, exactamente uno de cualquiera a
o b
se evalúa y volvió basa en la booleana valor de condition
. Si se condition
evalúa como True
, entonces a
se evalúa y se devuelve pero b
se ignora, o bien cuando b
se evalúa y se devuelve pero a
se ignora.
Esto permite un cortocircuito porque cuando condition
es verdadero solo a
se evalúa y b
no se evalúa en absoluto, pero cuando condition
es falso solo b
se evalúa y a
no se evalúa en absoluto.
Por ejemplo:
>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'
Tenga en cuenta que los condicionales son una expresión , no una declaración . Esto significa que no puede usar declaraciones de asignación pass
u otras declaraciones dentro de una expresión condicional :
>>> pass if False else x = 3
File "<stdin>", line 1
pass if False else x = 3
^
SyntaxError: invalid syntax
Sin embargo, puede usar expresiones condicionales para asignar una variable así:
x = a if True else b
Piense en la expresión condicional como el cambio entre dos valores. Es muy útil cuando estás en una situación de "un valor u otro", pero no hace mucho más.
Si necesita usar declaraciones, debe usar una if
declaración normal en lugar de una expresión condicional .
Tenga en cuenta que algunos Pythonistas lo desaprueban por varias razones:
condition ? a : b
operador ternario clásico de muchos otros lenguajes (como C, C ++, Go, Perl, Ruby, Java, Javascript, etc.), lo que puede generar errores cuando las personas no están familiarizadas con Python " sorprendente "comportamiento utilizarlo (pueden invertir el orden de los argumentos).if
' puede ser realmente útil y hacer que su script sea más conciso, realmente complica su código)Si tiene problemas para recordar el orden, recuerde que cuando lo lee en voz alta (casi) dice lo que quiere decir. Por ejemplo, x = 4 if b > 8 else 9
se lee en voz alta como x will be 4 if b is greater than 8 otherwise 9
.
Documentación oficial:
f(x) = |x| = x if x > 0 else -x
suena muy natural para los matemáticos. También es posible entenderlo como hacer A en la mayoría de casos, excepto cuando C entonces usted debe hacer B en vez ...
z = 3 + x if x < y else y
. Si x=2
y y=1
, puede esperar que produzca 4, pero en realidad produciría 1. z = 3 + (x if x > y else y)
es el uso correcto.
z = 3 + x if x < y else 3 + y
) o agrupar el condicional ( z = 3 + (x if x < y else y)
o z = (x if x < y else y) + 3
)
Puedes indexar en una tupla:
(falseValue, trueValue)[test]
test
necesita devolver verdadero o falso .
Puede ser más seguro implementarlo siempre como:
(falseValue, trueValue)[test == True]
o puede usar el incorporado bool()
para asegurar un valor booleano :
(falseValue, trueValue)[bool(<expression>)]
(lambda: print("a"), lambda: print("b"))[test==true]()
[]
s puede ser una expresión arbitraria. Además, por seguridad, puede probar explícitamente la veracidad escribiendo [bool(<expression>)]
. La bool()
función ha existido desde v2.2.1.
True
y False
como teclas: {True:trueValue, False:falseValue}[test]
no sé si esto es menos eficiente, pero al menos evita todo debate "elegante" versus "feo". No hay ambigüedad de que estés tratando con un booleano en lugar de un int.
Para versiones anteriores a la 2.5, está el truco:
[expression] and [on_true] or [on_false]
Puede dar resultados incorrectos cuando on_true
tiene un valor booleano falso. 1
Aunque tiene el beneficio de evaluar las expresiones de izquierda a derecha, lo cual es más claro en mi opinión.
<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
De la documentación :
Las expresiones condicionales (a veces llamadas "operador ternario") tienen la prioridad más baja de todas las operaciones de Python.
La expresión
x if C else y
primero evalúa la condición, C ( no x ); si C es verdadero, se evalúa x y se devuelve su valor; de lo contrario, y se evalúa y se devuelve su valor.Ver PEP 308 para más detalles sobre expresiones condicionales.
Nuevo desde la versión 2.5.
En 2006 se agregó un operador para una expresión condicional en Python como parte de la Propuesta de mejora de Python 308 . Su forma difiere del ?:
operador común y es:
<expression1> if <condition> else <expression2>
que es equivalente a:
if <condition>: <expression1> else: <expression2>
Aquí hay un ejemplo:
result = x if a > b else y
Otra sintaxis que se puede usar (compatible con versiones anteriores a 2.5):
result = (lambda:y, lambda:x)[a > b]()
donde los operandos se evalúan perezosamente .
Otra forma es indexando una tupla (que no es consistente con el operador condicional de la mayoría de los otros idiomas):
result = (y, x)[a > b]
o diccionario construido explícitamente:
result = {True: x, False: y}[a > b]
Otro método (menos confiable) pero más simple es usar and
y or
operadores:
result = (a > b) and x or y
Sin embargo, esto no funcionará si x
lo fuera False
.
Una posible solución es crear x
y y
enumerar o tuplas como se muestra a continuación:
result = ((a > b) and [x] or [y])[0]
o:
result = ((a > b) and (x,) or (y,))[0]
Si está trabajando con diccionarios, en lugar de usar un condicional ternario, puede aprovechar get(key, default)
, por ejemplo:
shell = os.environ.get('SHELL', "/bin/sh")
Fuente: ?: En Python en Wikipedia
result = {1: x, 0: y}[a > b]
es otra variante posible ( True
y en False
realidad son enteros con valores 1
y 0
)
Desafortunadamente, el
(falseValue, trueValue)[test]
la solución no tiene comportamiento de cortocircuito; así ambos falseValue
y trueValue
se evalúan independientemente de la condición. Esto podría ser subóptimo o incluso defectuoso (es decir, ambos trueValue
y falseValue
podrían ser métodos y tener efectos secundarios).
Una solución a esto sería
(lambda: falseValue, lambda: trueValue)[test]()
(ejecución retrasada hasta que se conozca al ganador;)), pero introduce inconsistencia entre objetos invocables y no invocables. Además, no resuelve el caso cuando se usan propiedades.
Y así, la historia continúa: elegir entre 3 soluciones mencionadas es una compensación entre tener la característica de cortocircuito, usar al menos Зython 2.5 (en mi humilde opinión ya no es un problema) y no ser propenso a errores de " trueValue
-evalúa a falso" .
if else if
.
Aquí solo trato de mostrar alguna diferencia importante ternary operator
entre un par de lenguajes de programación.
Operador ternario en Javascript
var a = true ? 1 : 0;
# 1
var b = false ? 1 : 0;
# 0
Operador ternario en Ruby
a = true ? 1 : 0
# 1
b = false ? 1 : 0
# 0
Operador ternario en Scala
val a = true ? 1 | 0
# 1
val b = false ? 1 | 0
# 0
Operador ternario en programación R
a <- if (TRUE) 1 else 0
# 1
b <- if (FALSE) 1 else 0
# 0
Operador ternario en Python
a = 1 if True else 0
# 1
b = 1 if False else 0
# 0
Para Python 2.5 y posteriores hay una sintaxis específica:
[on_true] if [cond] else [on_false]
En Python anteriores, no se implementa un operador ternario, pero es posible simularlo.
cond and on_true or on_false
Sin embargo, existe un problema potencial, que si se cond
evalúa True
y se on_true
evalúa False
, on_false
se devuelve en lugar de on_true
. Si desea este comportamiento, el método es correcto; de lo contrario, use esto:
{True: on_true, False: on_false}[cond is True] # is True, not == True
que puede ser envuelto por:
def q(cond, on_true, on_false)
return {True: on_true, False: on_false}[cond is True]
y usado de esta manera:
q(cond, on_true, on_false)
Es compatible con todas las versiones de Python.
q("blob", on_true, on_false)
retornos on_false
, mientras que on_true if cond else on_false
retornos on_true
. Una solución consiste en reemplazar cond
con cond is not None
en estos casos, aunque eso no es una solución perfecta.
bool(cond)
lugar de cond is True
? El primero verifica la veracidad de cond
, el segundo verifica la igualdad de puntero con el True
objeto. Como lo destacó @AndrewCecil, "blob"
es verdad pero is not True
.
[on_false, on_True][cond is True]
para que la expresión se acorte.
A menudo puedes encontrar
cond and on_true or on_false
pero esto lleva a un problema cuando on_true == 0
>>> x = 0
>>> print x == 0 and 0 or 1
1
>>> x = 1
>>> print x == 0 and 0 or 1
1
donde esperarías para un operador ternario normal este resultado
>>> x = 0
>>> print 0 if x == 0 else 1
0
>>> x = 1
>>> print 0 if x == 0 else 1
1
¿Python tiene un operador condicional ternario?
Si. Del archivo de gramática :
test: or_test ['if' or_test 'else' test] | lambdef
La parte de interés es:
or_test ['if' or_test 'else' test]
Entonces, una operación condicional ternaria tiene la forma:
expression1 if expression2 else expression3
expression3
será evaluado perezosamente (es decir, evaluado solo si expression2
es falso en un contexto booleano). Y debido a la definición recursiva, puede encadenarlos indefinidamente (aunque puede considerarse un mal estilo).
expression1 if expression2 else expression3 if expression4 else expression5 # and so on
Tenga en cuenta que cada if
debe seguirse con un else
. Las personas que aprenden las comprensiones de listas y las expresiones generadoras pueden encontrar que esta es una lección difícil de aprender: lo siguiente no funcionará, ya que Python espera una tercera expresión para otra cosa:
[expression1 if expression2 for element in iterable]
# ^-- need an else here
que plantea a SyntaxError: invalid syntax
. Entonces, lo anterior es una lógica incompleta (tal vez el usuario espera un no-op en la condición falsa) o lo que se pretende es usar la expresión2 como filtro; observa que lo siguiente es Python legal:
[expression1 for element in iterable if expression2]
expression2
funciona como un filtro para la comprensión de la lista y no es un operador condicional ternario.
Puede resultarle algo doloroso escribir lo siguiente:
expression1 if expression1 else expression2
expression1
tendrá que ser evaluado dos veces con el uso anterior. Puede limitar la redundancia si es simplemente una variable local. Sin embargo, un lenguaje Pythonic común y eficaz para este caso de uso es utilizar or
el comportamiento de acceso directo:
expression1 or expression2
que es equivalente en semántica. Tenga en cuenta que algunas guías de estilo pueden limitar este uso por motivos de claridad, ya que tiene mucho significado en muy poca sintaxis.
expression1 or expression2
ser similar y con los mismos inconvenientes / positivos que expression1 || expression2
en JavaScript
expressionN
para todas las instancias es consistente, puede ser más fácil de entender con nombres que distingan la expresión de prueba condicional de las dos expresiones de resultado; por ejemplo, result1 if condition else result2
. Esto es especialmente evidente cuando se anidan (también conocido como encadenamiento): result1 if condition1 else result2 if condition2 else result3
. ¿Ves cuánto mejor se lee de esta manera?
Simulando el operador ternario de python.
Por ejemplo
a, b, x, y = 1, 2, 'a greather than b', 'b greater than a'
result = (lambda:y, lambda:x)[a > b]()
salida:
'b greater than a'
result = (y, x)[a < b]
qué utiliza la lambda
función ?
El operador condicional ternario simplemente permite probar una condición en una sola línea reemplazando el multilínea if-else haciendo que el código sea compacto.
[on_true] if [expresión] 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")
El enfoque anterior se puede escribir como:
# 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
no es en realidad una reescritura del operador ternario, y producirá una salida diferente para los valores seleccionados de a y b (específicamente si uno es un tipo que implementa un __ne__
método extraño ).
Puedes hacerlo :-
[condition] and [expression_1] or [expression_2] ;
Ejemplo:-
print(number%2 and "odd" or "even")
Esto imprimirá "impar" si el número es impar o "par" si el número es par.
Nota: - 0, Ninguno, Falso, lista vacía, emptyString se evalúa como Falso. Y cualquier dato que no sea 0 se evalúa como Verdadero.
si la condición [condición] se convierte en "Verdadero", entonces se evaluará la expresión_1 pero no la expresión_2. Si "y" algo con 0 (cero), el resultado siempre será fasle. Así que en la siguiente declaración,
0 and exp
La expresión exp no se evaluará en absoluto ya que "y" con 0 siempre se evaluarán a cero y no hay necesidad de evaluar la expresión. Así es como funciona el compilador, en todos los idiomas.
En
1 or exp
la expresión exp no se evaluará en absoluto ya que "o" con 1 siempre será 1. Por lo tanto, no se molestará en evaluar la expresión exp ya que el resultado será 1 de todos modos. (métodos de optimización del compilador).
Pero en caso de
True and exp1 or exp2
La segunda expresión exp2 no se evaluará, ya True and exp1
que sería True cuando exp1 no sea falso.
Similarmente en
False and exp1 or exp2
La expresión exp1 no se evaluará ya que False es equivalente a escribir 0 y hacer "y" con 0 sería 0, pero después de exp1 ya que se usa "o", evaluará la expresión exp2 después de "o".
Nota: - Este tipo de ramificación usando "o" y "y" solo se puede usar cuando la expresión_1 no tiene un valor de Verdad de Falso (o 0 o Ninguno o una lista vacía [] o una cadena de caracteres vacía ''), ya que si la expresión_1 se convierte en Falso, entonces la expresión_2 se evaluará debido a la presencia "o" entre exp_1 y exp_2.
En caso de que aún desee que funcione para todos los casos, independientemente de los valores de verdad exp_1 y exp_2, haga lo siguiente:
[condition] and ([expression_1] or 1) or [expression_2] ;
x = [condition] and ([expression_1] or 1) or [expression_2]
y se expression_1
evalúa como falso, x
será 1
, no expression_1
. Usa la respuesta aceptada.
Más un consejo que una respuesta (no es necesario repetir lo obvio por enésima vez), pero a veces lo uso como un atajo de línea en tales construcciones:
if conditionX:
print('yes')
else:
print('nah')
, se convierte en:
print('yes') if conditionX else print('nah')
Algunos (muchos :) pueden fruncir el ceño por no ser un pitón (incluso, ruby-ish :), pero personalmente lo encuentro más natural, es decir, cómo lo expresarías normalmente, además de un poco más visualmente atractivo en grandes bloques de código.
print( 'yes' if conditionX else 'nah' )
a tu respuesta. :-)
print()
, en ambos casos - y se ve un poco más Pythonic, tengo que admitir :) Pero lo que si las expresiones / funciones no son lo mismo - como print('yes') if conditionX else True
- para conseguir la print()
única en TruthyconditionX
print('yes') if conditionX else print('nah')
es que proporciona un SyntaxError en Python2.
print "yes"
, mientras que en Python 3 es una función print("yes")
. Eso se puede resolver ya sea usándolo como una declaración, o mejor - from future import print_function
.
Una de las alternativas a la expresión condicional de Python.
"yes" if boolean else "no"
es el siguiente:
{True:"yes", False:"no"}[boolean]
que tiene la siguiente extensión agradable:
{True:"yes", False:"no", None:"maybe"}[boolean_or_none]
La alternativa más corta sigue siendo:
("no", "yes")[boolean]
pero no hay alternativa a
yes() if boolean else no()
si quieres evitar la evaluación de yes()
y no()
, porque en
(no(), yes())[boolean] # bad
ambos no()
y yes()
son evaluados.
Muchos lenguajes de programación derivados C
generalmente tienen la siguiente sintaxis de operador condicional ternario:
<condition> ? <expression1> : <expression2>
Al principio, el D ictator
Python
B ovo F o L ife (me refiero a Guido van Rossum, por supuesto) lo rechazó (como un estilo no pitónico), ya que es bastante difícil de entender para las personas que no están acostumbradas al lenguaje. Además, el signo de dos puntos ya tiene muchos usos . Después de que se aprobó PEP 308 , finalmente recibió su propia expresión condicional de acceso directo (lo que usamos ahora):C
:
Python
Python
<expression1> if <condition> else <expression2>
Entonces, primero evalúa la condición. Si regresa True
, se evaluará la expresión1 para dar el resultado; de lo contrario , se evaluará la expresión2 . Debido a la mecánica de Lazy Evaluation , solo se ejecutará una expresión.
Aquí hay algunos ejemplos (las condiciones se evaluarán de izquierda a derecha):
pressure = 10
print('High' if pressure < 20 else 'Critical')
# Result is 'High'
Los operadores ternarios se pueden encadenar en serie:
pressure = 5
print('Normal' if pressure < 10 else 'High' if pressure < 20 else 'Critical')
# Result is 'Normal'
El siguiente es el mismo que el anterior:
pressure = 5
if pressure < 20:
if pressure < 10:
print('Normal')
else:
print('High')
else:
print('Critical')
# Result is 'Normal'
Espero que esto ayude.
Como ya se respondió, sí, hay un operador ternario en python:
<expression 1> if <condition> else <expression 2>
Información Adicional:
Si <expression 1>
es la condición, puede usar la evaluación de cortocircuito :
a = True
b = False
# Instead of this:
x = a if a else b
# You could use Short-cirquit evaluation:
x = a or b
PD: Por supuesto, una evaluación de cortocircuito no es un operador ternario, pero a menudo el ternario se usa en casos donde el cortocircuito sería suficiente.
short-circuit
evaluación.
SÍ, Python tiene un operador ternario, aquí está la sintaxis y un código de ejemplo para demostrar lo mismo :)
#[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
realmente no es una buena opción, ya que esto dará un SyntaxError en Python2.
Python tiene una forma ternaria para tareas; Sin embargo, puede haber incluso una forma más corta que las personas deben tener en cuenta.
Es muy común necesitar asignar a una variable un valor u otro dependiendo de una condición.
>>> li1 = None
>>> li2 = [1, 2, 3]
>>>
>>> if li1:
... a = li1
... else:
... a = li2
...
>>> a
[1, 2, 3]
^ Esta es la forma larga de hacer tales tareas.
A continuación se muestra la forma ternaria. Pero esta no es la forma más sucinta: vea el último ejemplo.
>>> a = li1 if li1 else li2
>>>
>>> a
[1, 2, 3]
>>>
Con Python, simplemente puede usar or
para tareas alternativas.
>>> a = li1 or li2
>>>
>>> a
[1, 2, 3]
>>>
Lo anterior funciona como li1
es None
y el interp trata eso como falso en expresiones lógicas. Luego, el interp continúa y evalúa la segunda expresión, que no es None
y no es una lista vacía, por lo que se asigna a a.
Esto también funciona con listas vacías. Por ejemplo, si desea asignar a
la lista que tenga elementos.
>>> li1 = []
>>> li2 = [1, 2, 3]
>>>
>>> a = li1 or li2
>>>
>>> a
[1, 2, 3]
>>>
Sabiendo esto, puede simplemente realizar tales tareas cada vez que las encuentre. Esto también funciona con cadenas y otros iterables. Puede asignar a
cualquier cadena que no esté vacía.
>>> s1 = ''
>>> s2 = 'hello world'
>>>
>>> a = s1 or s2
>>>
>>> a
'hello world'
>>>
Siempre me ha gustado la sintaxis de C ternary, ¡pero Python va un paso más allá!
Entiendo que algunos pueden decir que esta no es una buena opción estilística porque se basa en mecanismos que no son evidentes de inmediato para todos los desarrolladores. Personalmente no estoy de acuerdo con ese punto de vista. Python es un lenguaje rico en sintaxis con muchos trucos idiomáticos que no son evidentes de inmediato para el dabler. Pero cuanto más aprenda y comprenda la mecánica del sistema subyacente, más lo apreciará.
Otras respuestas hablan correctamente sobre el operador ternario de Python. Me gustaría complementar mencionando un escenario para el que se usa a menudo el operador ternario, pero para el cual existe una mejor expresión idiomática. Este es el escenario de usar un valor predeterminado.
Supongamos que queremos usar option_value
un valor predeterminado si no está configurado:
run_algorithm(option_value if option_value is not None else 10)
o simplemente
run_algorithm(option_value if option_value else 10)
Sin embargo, una solución cada vez mejor es simplemente escribir
run_algorithm(option_value or 10)
si la variable está definida y desea verificar si tiene valor, puede simplemente 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)
saldrá
no Input
no Input
no Input
hello
['Hello']
True
x if x else y
, pero no x if z else y
.
Una forma ordenada de encadenar múltiples operadores:
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
Encuentro engorroso la sintaxis predeterminada de Python val = a if cond else b
, así que a veces hago esto:
iif = lambda (cond, a, b): a if cond else b
# so I can then use it like:
val = iif(cond, a, b)
Por supuesto, tiene la desventaja de evaluar siempre ambos lados (a y b), pero la sintaxis es mucho más clara para mí.
val = a if cond else b
declaración más simple .
is_spacial=True if gender = "Female" else (True if age >= 65 else False)
** **
Se puede anidar según su necesidad. la mejor de las suertes
** **