¿Python tiene un operador condicional ternario?
-
23-08-2019 - |
Pregunta
Si Python no tiene un operador condicional ternario, ¿es posible simular uno utilizando otras construcciones del lenguaje?
Solución
Sí, era añadió en la versión 2.5. La sintaxis de la expresión es:
a if condition else b
Primera condition
se evalúa, a continuación, uno de o bien a
o b
se evalúa exactamente y volvió basado en el valor booleano de condition
. Si se evalúa como condition
True
, entonces a
se evalúa y se devuelve pero b
se ignora, o bien cuando se evalúa b
y regresó, pero se ignora a
.
Esto permite un cortocircuito porque cuando condition
es cierto sólo se evalúa a
y b
no se evalúa en absoluto, pero cuando condition
es falsa sólo se evalúa b
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 un expresión , no un instrucción . Esto significa que no puede utilizar las instrucciones de asignación o pass
u otras declaraciones dentro de un condicional expresión
>>> pass if False else x = 3
File "<stdin>", line 1
pass if False else x = 3
^
SyntaxError: invalid syntax
Puede, sin embargo, utilizar expresiones condicionales para asignar una variable de esta manera:
x = a if True else b
Piense de la expresión condicional como el cambio entre dos valores. Es muy útil cuando se está en un 'un valor u otro' situación, pero no hace mucho más.
Si es necesario utilizar declaraciones, usted tiene que utilizar un if
normales declaración en lugar de un condicional expresión .
Tenga en cuenta que es mal visto por algunos Pythonistas por varias razones:
- El orden de los argumentos es diferente de las del operador ternario
condition ? a : b
clásico de muchos otros lenguajes (como C, C ++, Go, Perl, Ruby, Java, JavaScript, etc.), lo que puede conducir a errores cuando la gente familiarizados con el comportamiento de "sorprendente" de Python lo utilizan (que pueden revertir el orden de los argumentos). - Para algunas personas es "difícil de manejar", ya que va en contra de la corriente normal de pensamiento (pensamiento de la condición primera y luego los efectos).
- razones estilísticas. (Aunque el 'inline
if
' puede ser realmente útil, y hacer su escritura más concisa, lo que realmente complica su código)
Si usted está teniendo problemas para recordar el orden, a continuación, recordar que cuando se lee en voz alta, que (casi) diga 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
.
La documentación oficial:
Otros consejos
Es posible indexar en una tupla:
(falseValue, trueValue)[test]
test
necesita volver True o false .
Podría ser más seguro para poner en práctica siempre como:
(falseValue, trueValue)[test == True]
o puede utilizar el incorporado en la bool()
para asegurar una valor booleano :
(falseValue, trueValue)[bool(<expression>)]
En versiones anteriores a 2.5, está el truco:
[expression] and [on_true] or [on_false]
Se puede dar resultados erróneos cuando on_true
tiene un valor booleano falso. 1
Aunque tiene el beneficio de la evaluación de expresiones de izquierda a derecha, lo que 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
la documentación:
Las expresiones condicionales (a veces llamado un “operador ternario”) tienen la prioridad más baja de todas las operaciones de Python.
El
x if C else y
expresión se evalúa primero la condición, C ( no x ); si C es cierto, x se evalúa y se devuelve su valor; de lo contrario, y se evalúa y se devuelve su valor.PEP 308 para más detalles acerca de las expresiones condicionales.
Nuevo desde la versión 2.5.
Un operador para una expresión condicional en Python se añadió en 2006 como parte de Enhancement Python propuesta 308 . Su forma difiere de operador ?:
común y que es:
<expression1> if <condition> else <expression2>
que es equivalente a:
if <condition>: <expression1> else: <expression2>
Aquí es un ejemplo:
result = x if a > b else y
Otra sintaxis que se puede utilizar (compatible con versiones antes de 2.5):
result = (lambda:y, lambda:x)[a > b]()
donde operandos son perezosamente evaluado .
Otra forma es mediante la indexación de una tupla (que no es consistente con el operador condicional de la mayoría de otros idiomas):
result = (y, x)[a > b]
o diccionario construido explícitamente:
result = {True: x, False: y}[a > b]
Otro método (menos fiables), pero más simple es utilizar los operadores and
y or
:
result = (a > b) and x or y
Sin embargo, esto no funcionará si se x
False
.
Una posible solución consiste en hacer listas o tuplas x
y y
como en el siguiente:
result = ((a > b) and [x] or [y])[0]
o
result = ((a > b) and (x,) or (y,))[0]
Si se trabaja con los diccionarios, en lugar de utilizar un condicional ternario, se puede tomar ventaja de get(key, default)
, por ejemplo:
shell = os.environ.get('SHELL', "/bin/sh")
Fuente: :? En Python en Wikipedia
Por desgracia, la
(falseValue, trueValue)[test]
solución no tiene el comportamiento de cortocircuito; por lo tanto se evalúan tanto falseValue
y trueValue
independientemente de la condición. Esto podría ser subóptima o incluso con errores (es decir, tanto trueValue
y falseValue
podrían ser métodos y tienen efectos secundarios).
Una solución a esto sería
(lambda: falseValue, lambda: trueValue)[test]()
(ejecución retrasa hasta que se conoce el ganador;)), pero introduce inconsistencia entre los objetos desembolsadas y no exigible. Además, no resuelve el caso cuando se utilizan las propiedades.
Y así va la historia - la elección entre 3 soluciones mencionadas es una solución de compromiso entre tener la función de cortocircuito, utilizando al menos Зython 2.5 (en mi humilde opinión no es un problema ya) y no ser propenso a "trueValue
-evalúa a " errores es falsa.
ternario Operador de programación diferentes idiomas
A continuación, sólo trato de mostrar alguna diferencia importante en ternary operator
entre un par de lenguajes de programación.
ternario operador en Javascript
var a = true ? 1 : 0;
# 1
var b = false ? 1 : 0;
# 0
ternario operador 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 la 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
En Python 2.5 y más reciente hay una sintaxis específica:
[on_true] if [cond] else [on_false]
En pitones un operador ternario de más edad no está implementado pero es posible simularlo.
cond and on_true or on_false
Sin embargo, existe un problema potencial, que si se evalúa como cond
True
y on_true
evalúa a continuación False
on_false
se devuelve en lugar de on_true
. Si desea que este comportamiento del método está bien, de lo contrario usar 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 se utiliza de esta manera:
q(cond, on_true, on_false)
Es compatible con todas las versiones de Python.
Es posible que a menudo se encuentran
cond and on_true or on_false
pero esto conduce a un problema cuando == 0 on_true
>>> x = 0
>>> print x == 0 and 0 or 1
1
>>> x = 1
>>> print x == 0 and 0 or 1
1
donde se puede esperar de un operador ternario normal de este resultado
>>> x = 0
>>> print 0 if x == 0 else 1
0
>>> x = 1
>>> print 0 if x == 0 else 1
1
¿Tiene Python tiene un operador condicional ternario?
test: or_test ['if' or_test 'else' test] | lambdef
La parte de interés es:
or_test ['if' or_test 'else' test]
Por lo tanto, una operación condicional ternario es de la forma:
expression1 if expression2 else expression3
expression3
será evaluada perezosamente (es decir, evalúa sólo si expression2
es falso en un contexto booleano). Y debido a la definición recursiva, se les puede encadenar de forma indefinida (aunque puede considerarse un mal estilo.)
expression1 if expression2 else expression3 if expression4 else expression5 # and so on
Nota sobre el uso:
Tenga en cuenta que cada if
debe ser seguido con un else
. Personas que están aprendiendo listas por comprensión y expresiones generadoras pueden encontrar que esto sea una lección difícil de aprender - la siguiente no funcionará, como Python espera una tercera expresión de una cosa:
[expression1 if expression2 for element in iterable]
# ^-- need an else here
lo que plantea un SyntaxError: invalid syntax
.
Así que la anterior es o bien una pieza incompleta de la lógica (tal vez el usuario espera un no-op en la condición falso) o lo puede estar destinado es utilizar expression2 como un filtro - observa que la siguiente es Python legal:
[expression1 for element in iterable if expression2]
expression2
funciona como un filtro para la lista de la comprensión, y es no un operador condicional ternario.
Sintaxis alternativa para un caso más estrecha:
Puede resultar algo doloroso para escribir lo siguiente:
expression1 if expression1 else expression2
expression1
tendrá que ser evaluado dos veces con el uso anteriormente. Se puede limitar la redundancia si es simplemente una variable local. Sin embargo, un lenguaje común y Pythonic performant para este caso de uso es utilizar el comportamiento acortando de or
:
expression1 or expression2
que es equivalente en la semántica. Tenga en cuenta que algunas guías de estilo pueden limitar este uso por motivos de claridad -. Sí paquete de un montón de significado en muy poco sintaxis
Simulando el operador ternario pitón.
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'
Puedes hacerlo :-
[condition] and [expression_1] or [expression_2] ;
Ejemplo:-
print(number%2 and "odd" or "even")
Esto imprimiría "impar" si el número es impar o "par" si el número es par.
El resultado :- Si la condición es verdadera, se ejecuta exp_1; de lo contrario, se ejecuta exp_2.
Nota :- 0, Ninguno, Falso, lista vacía, cadena vacía se evalúa como Falso.Y cualquier dato distinto de 0 se evalúa como Verdadero.
Así es como funciona:
Si la condición [condición] se vuelve "Verdadera", entonces, se evaluará expresión_1 pero no expresión_2.Si "y" algo con 0 (cero), el resultado siempre será sencillo. Entonces, 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á como cero y no hay necesidad de evaluar la expresión.Así funciona el propio compilador, en todos los idiomas.
En
1 or exp
la expresión exp no será evaluada en absoluto ya que "o" con 1 siempre será 1.Por lo tanto, no será necesario 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 será evaluada ya que True and exp1
sería Verdadero cuando exp1 no sea falso.
De manera similar en
False and exp1 or exp2
La expresión exp1 no será evaluada ya que False equivale a escribir 0 y hacer "y" con 0 sería 0 en sí mismo, pero después de exp1 ya que se usa "o", evaluará la expresión exp2 después de "o".
Nota:- Este tipo de bifurcación usando "o" y "y" solo se puede usar cuando la expresión_1 no tiene un valor de Verdad de False (o 0 o Ninguno o lista vacía [ ] o cadena vacía ''.) ya que si expresión_1 se vuelve False, entonces la expresión_2 será evaluada 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 cuáles sean los valores de verdad de exp_1 y exp_2, haga esto:
[condition] and ([expression_1] or 1) or [expression_2] ;
operador condicional ternario simplemente permite probar una condición en una sola línea de la sustitución de la multilínea si-else haciendo que el compacto código.
Sintaxis:
[on_true] si [expresión] más [on_false]
1- Método simple de usar operador ternario:
# 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
2- método directo de la utilización de tuplas, diccionario, y lambda:
# 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
3- operador ternario puede ser escrito como anidado si-else:
# 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")
Por encima de enfoque 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
Más una punta de una respuesta (no es necesario repetir la obvia para la centésima vez), pero a veces lo uso como un acceso directo oneliner 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 a él como unpythonic (incluso, :) rubí-ish, pero personalmente encuentro más natural - es decir, cómo se había expresan normalmente, además de un poco más atractiva visualmente en grandes bloques de código.
a if condition else b
Sólo memorizar esta pirámide si tiene problemas para recordar:
condition
if else
a b
SÍ, pitón tiene un operador ternario, aquí es la sintaxis y un código de ejemplo para demostrar el 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")
Muchos lenguajes de programación derivados de C
por lo general tienen la siguiente sintaxis del operador condicional ternario:
<condition> ? <expression1> : <expression2>
Al principio, el
Python
B enevolent D ictator F o L ife (I significa Guido van Rossum , por supuesto) lo rechazaron (como el estilo no Pythonic), ya que es muy difícil de entender para las personas que no utilizan paraC
idioma. Además, el signo de colon:
ya tiene muchos usos enPython
. Después de PEP 308 fue aprobado,Python
finalmente recibió su propio acceso directo de la expresión condicional (lo que usamos ahora):
<expression1> if <condition> else <expression2>
Por lo tanto, en primer lugar se evalúa la condición. Si devuelve True
, expresión1 será evaluado para dar el resultado, de lo contrario expresión2 será evaluada. Debido a Lazy Evaluación - mecánica. Sólo una expresión será ejecutado
He aquí algunos ejemplos (condiciones serán evaluadas de izquierda a derecha):
pressure = 10
print('High' if pressure < 20 else 'Critical')
# Result is 'High'
Los operadores ternarios pueden ser encadenados en serie:
pressure = 5
print('Normal' if pressure < 10 else 'High' if pressure < 20 else 'Critical')
# Result is 'Normal'
La 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.
Una de las alternativas a la de Python expresión condicional 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 alterativa más corto permanece:
("no", "yes")[boolean]
pero no hay alternativa si se quiere evitar la evaluación de ambos yes()
y no()
en lo siguiente:
yes() if [condition] else no()
Si se define variable y que desea comprobar si tiene valor sólo se puede 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)
salida voluntad
no Input
no Input
no Input
hello
['Hello']
True
una clara forma de cadena de 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