¿Python tiene un operador condicional ternario?

6866

Si Python no tiene un operador condicional ternario, ¿es posible simular uno usando otras construcciones de lenguaje?

9
  • 170
    En la documentación oficial de Python 3.0 a la que se hace referencia en un comentario anterior, esto se conoce como "expresiones_condicionales" y está definido de manera muy críptica. Esa documentación ni siquiera incluye el término "ternario", por lo que sería difícil encontrarlo a través de Google a menos que supiera exactamente qué buscar. La documentación de la versión 2 es algo más útil e incluye un enlace a "PEP 308" , que incluye una gran cantidad de contexto histórico interesante relacionado con esta pregunta. Brent Bradburn 10 de enero de 2013 a las 5:57
  • 35
    "ternario" (que tiene tres entradas) es una propiedad consecuencial de este impulso, no una propiedad definitoria del concepto. Por ejemplo: SQL tiene case [...] { when ... then ...} [ else ... ] endun efecto similar pero no ternario en absoluto. user313114 15/12/2014 a las 21:14
  • 13
    también ISO / IEC 9899 (el estándar de lenguaje de programación C) sección 6.5.15 lo llama el "operador condtitional"user313114 15/12/2014 a las 21:20
  • 11
    Wikipedia cubre esto a fondo en el artículo " ?: ". HelloGoodbye 9 de junio de 2016 a las 8:11
  • 13
    En los años transcurridos desde el comentario de Nobar, la documentación de la expresión condicional se ha actualizado para decir Expresiones condicionales (a veces llamadas "operador ternario") ...Scott Martin 15/08/18 a las 13:25
7928

Sí, se agregó en la versión 2.5. La sintaxis de la expresión es:

a if condition else b

Primero conditionse evalúa, luego exactamente uno de ao bse evalúa y se devuelve según el valor booleano de condition. Si se conditionevalúa como True, entonces ase evalúa y se devuelve pero bse ignora, o bien, cuando bse evalúa y se devuelve pero ase ignora.

Esto permite el cortocircuito porque cuando conditiones verdadero solo ase evalúa y bno se evalúa en absoluto, pero cuando conditiones falso solo bse evalúa y ano 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 passu 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 como esta:

x = a if True else b

Piense en la expresión condicional como un 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:

  • El orden de los argumentos es diferente al del condition ? a : boperador ternario clásico de muchos otros lenguajes (como C, C ++, Go, Perl, Ruby, Java, Javascript, etc.), lo que puede generar errores cuando la gente no está familiarizada con Python " comportamiento sorprendente "utilícelo (pueden invertir el orden de los argumentos).
  • Algunos lo encuentran "difícil de manejar", ya que va en contra del flujo normal de pensamiento (pensar primero en la condición y luego en los efectos).
  • Razones estilísticas. (Aunque el 'en línea 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 9se lee en voz alta como x will be 4 if b is greater than 8 otherwise 9.

Documentación oficial:

12
  • 322
    El orden puede parecer extraño para los codificadores, sin embargo, f(x) = |x| = x if x > 0 else -xsuena muy natural para los matemáticos. También puede entenderlo como lo hace A en la mayoría de los casos, excepto cuando C, entonces debería hacer B en su lugar ...yota 25 de enero de 2016 a las 15:07
  • 147
    Tenga cuidado con el orden de las operaciones cuando utilice esto. Por ejemplo, la línea z = 3 + x if x < y else y. Si x=2y y=1, podría esperar que produzca 4, pero en realidad produciría 1. z = 3 + (x if x > y else y)es el uso correcto. Kal Zekdor 6 de marzo de 2016 a las 9:23
  • 14
    El punto era que si desea realizar evaluaciones adicionales después de que se evalúe el condicional, como agregar un valor al resultado, deberá agregar la expresión adicional a ambos lados ( 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)Kal Zekdor 15/04/2016 a las 0:36
  • 5
    @MrGeek, veo lo que quieres decir, así que básicamente estarías anidando las operaciones: `" foo "if Bool else (" bar "if Bool else" foobar ")`Dimesio 11 de agosto de 2017 a las 0:04
  • 5
    Los programadores necesitan una formulación precisa y correcta incluso más que los matemáticos, porque en matemáticas siempre se recurre a conceptos subyacentes. Un argumento convincente es el operador%, imitando la forma en que se usa "mod" en matemáticas habría sido un desastre. Entonces no, no acepto tu argumento. Es como adherirse a unidades imperiales. Albert GroetjesAlbert van der Horst 17 de junio de 2018 a las 12:50
890

Puede indexar en una tupla:

(falseValue, trueValue)[test]

testdebe devolver Verdadero o Falso .
Podría 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>)]
12
  • 659
    Tenga en cuenta que este siempre evalúa todo, mientras que la construcción if / else solo evalúa la expresión ganadora. SilverbackNet 4 de febrero de 2011 a las 2:25
  • 134
    (lambda: print("a"), lambda: print("b"))[test==true]()Dustin Getz 8/03/12 a las 19:31
  • 19
    Cabe señalar que lo que está dentro de la []s puede ser una expresión arbitraria. Además, por seguridad, puede probar explícitamente la veracidad por escrito [bool(<expression>)]. La bool()función existe desde v2.2.1. martineau 31 de mayo de 2012 a las 18:20
  • 12
    Hice un truco similar, solo una o dos veces, pero lo hice, indexando en un diccionario con Truey Falsecomo las claves: {True:trueValue, False:falseValue}[test] no sé si esto es menos eficiente, pero al menos evita todo Debate entre "elegante" y "feo". No hay ninguna ambigüedad de que esté tratando con un booleano en lugar de un int. JDM 1 mar 16 a las 18:43
  • 9
387

Para las versiones anteriores a la 2.5, existe el truco:

[expression] and [on_true] or [on_false]

Puede dar resultados incorrectos cuando on_true tiene un valor booleano falso. 1
Aunque tiene la ventaja de evaluar expresiones de izquierda a derecha, lo cual es más claro en mi opinión.

1. ¿Existe un equivalente de C's ”?:” Operador ternario?

4
  • 73
    El remedio es usar (test y [true_value] o [false_value]) [0], lo que evita esta trampa. ThomasH 21/10/09 a las 15:33
  • 7
    El operador ternario generalmente se ejecuta más rápido (a veces entre un 10 y un 25%). volcano 13/01/2014 a las 7:52
  • 7
    @volcano ¿Tienes fuente para mí? OrangeTux 5 de agosto de 2014 a las 12:30
  • 5
    @OrangeTux Aquí está el código desensamblado . Usar el método sugerido por ThomasH sería incluso más lento. mbomb007 19/03/18 a las 20:59
306

<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
3
  • 89
    Éste enfatiza la intención principal del operador ternario: la selección de valores. También muestra que se puede encadenar más de un ternario en una sola expresión. Roy Tinker 4/10/10 a las 21:14
  • 6
    @ Craig, estoy de acuerdo, pero también es útil saber qué pasará cuando no haya paréntesis. En código real, yo también tendería a insertar paréntesis explícitos. Jon Coombs 1 dic 2014 a las 21:30
  • Uso:return 3 if t > 10 else t/2mins 25 oct.20 a las 16:41
178

De la documentación :

Conditional expressions (sometimes called a “ternary operator”) have the lowest priority of all Python operations.

The expression x if C else y first evaluates the condition, C (not x); if C is true, x is evaluated and its value is returned; otherwise, y is evaluated and its value is returned.

See PEP 308 for more details about conditional expressions.

Nuevo desde la versión 2.5.

139

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 utilizar (compatible con versiones anteriores a la 2.5):

result = (lambda:y, lambda:x)[a > b]()

donde los operandos se evalúan de forma perezosa .

Otra forma es indexando una tupla (que no es consistente con el operador condicional de la mayoría de los otros lenguajes):

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 operadores andy or:

result = (a > b) and x or y

sin embargo, esto no funcionará si xlo fuera False.

Una posible solución es hacer xy ylistas o tuplas como en el siguiente:

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 utilizar un condicional ternario, puede aprovechar get(key, default), por ejemplo:

shell = os.environ.get('SHELL', "/bin/sh")

Fuente: ?: En Python en Wikipedia

1
  • 1
    result = {1: x, 0: y}[a > b]es otra variante posible ( Truey en Falserealidad son números enteros con valores 1y 0)Walter Tross 9 feb 2019 a las 18:07
106

Desafortunadamente, el

(falseValue, trueValue)[test]

la solución no tiene comportamiento de cortocircuito; por lo tanto, ambos falseValuey trueValuese evalúan independientemente de la condición. Esto podría ser subóptimo o incluso con errores (es decir, ambos trueValuey falseValuepodrí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 conoce el ganador;)), pero introduce inconsistencias entre los objetos invocables y no invocables. Además, no resuelve el caso al usar propiedades.

Y así sigue la historia: elegir entre las 3 soluciones mencionadas es una compensación entre tener la función 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" .

1
  • 3
    Si bien el truco de la tupla de lambdas funciona, toma aproximadamente 3 veces más tiempo que el operador ternario. Solo es probable que sea una idea razonable si puede reemplazar una larga cadena de if else if. Perkins 11 oct 2018 a las 17:34
85

Operador ternario en diferentes lenguajes de programación

Aquí solo trato de mostrar alguna diferencia importante ternary operatorentre un par de lenguajes de programación.

Ternary Operator in Javascript

var a = true ? 1 : 0;
# 1
var b = false ? 1 : 0;
# 0

Ternary Operator in Ruby

a = true ? 1 : 0
# 1
b = false ? 1 : 0
# 0

Ternary operator in Scala

val a = true ? 1 | 0
# 1
val b = false ? 1 | 0
# 0

Ternary operator in R programming

a <- if (TRUE) 1 else 0
# 1
b <- if (FALSE) 1 else 0
# 0

Ternary operator in Python

a = 1 if True else 0
# 1
b = 1 if False else 0
# 0
6
  • 15
  • 7
    Puede parecer obstinado; pero lo que esencialmente dice es que es probable que la sintaxis de Python la entienda una persona que nunca vio un operador ternario, mientras que muy pocas personas entenderán la sintaxis más habitual a menos que se les haya dicho primero lo que significa. fralau 10 de ene. De 2018 a las 17:12
  • 2
    Algol68: a = .if. .cierto. .luego. 1 .más. 0 .fi. Esto puede expresarse también a = (. True. | 1 | 0) Como de costumbre, Algol68 es una mejora con respecto a sus sucesores. Albert van der Horst 17 de junio de 2018 a las 12:55
  • algo simple como print a || '<alt text>'en ruby ​​es pita en pythonprint a if a is not None else 'alt text'Varun Garg 5 nov.20 a las 8:44
  • 1
    @VarunGarg Pero, por supuesto, puedes decirlo print(a or 'alt text')en Python. lenz 15 nov.20 a las 20:24
70

Para Python 2.5 y versiones posteriores, hay una sintaxis específica:

[on_true] if [cond] else [on_false]

En Pythons más antiguos 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 condevalúa Truey on_trueevalúa Falseentonces on_falsese devuelve en lugar de on_true. Si desea este comportamiento, el método está bien, 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 se usa de esta manera:

q(cond, on_true, on_false)

Es compatible con todas las versiones de Python.

4
  • 2
    El comportamiento no es idéntico: q("blob", on_true, on_false)devuelve on_false, mientras que on_true if cond else on_falsedevuelve on_true. Una solución alternativa es reemplazar condcon cond is not Noneen estos casos, aunque esa no es una solución perfecta. user3317 26 de septiembre de 2012 a las 9:09
  • 5
    ¿Por qué no en bool(cond)lugar de cond is True? El primero comprueba la veracidad de cond, el segundo comprueba la igualdad de puntero con el Trueobjeto. Como lo destaca @AndrewCecil, "blob"es verdad pero lo es is not True. Jonas Kölker 11/11/2013 a las 16:11
  • ¡Vaya, eso se ve realmente hacky! :) Técnicamente, incluso puedes escribir [on_false, on_True][cond is True]para que la expresión sea más corta. Arseny 24 feb 2014 a las 11:51
  • No hay ningún cortocircuito en esta respuesta. Si on_true y on_false son costosos de llamar, esta es una mala respuesta. Hucker 28/03/19 a las 14:08
49

A menudo puedes encontrar

cond and on_true or on_false

pero esto conduce 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ía 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
0
44

Does Python have a ternary conditional operator?

Si. Desde el 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

expression3será evaluado de manera perezosa (es decir, evaluado solo si expression2es falso en un contexto booleano). Y debido a la definición recursiva, puede encadenarlos indefinidamente (aunque puede considerarse de mal estilo).

expression1 if expression2 else expression3 if expression4 else expression5 # and so on

Una nota sobre el uso:

Tenga en cuenta que cada uno ifdebe ir seguido de un else. Las personas que aprenden listas de comprensión y 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:

[expression1 if expression2 for element in iterable]
#                          ^-- need an else here

que genera un SyntaxError: invalid syntax. Entonces, lo anterior es una pieza de lógica incompleta (tal vez el usuario espera una operación no operativa en la condición falsa) o lo que se puede pretender es usar expression2 como filtro; tenga en cuenta que lo siguiente es Python legal:

[expression1 for element in iterable if expression2]

expression2funciona como un filtro para la comprensión de la lista y no es un operador condicional ternario.

Sintaxis alternativa para un caso más estrecho:

Puede resultarle algo doloroso escribir lo siguiente:

expression1 if expression1 else expression2

expression1tendrá que ser evaluado dos veces con el uso anterior. Puede limitar la redundancia si es simplemente una variable local. Sin embargo, un modismo Pythonic común y eficaz para este caso de uso ores el comportamiento de atajos de uso :

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: contiene mucho significado en muy poca sintaxis.

4
  • 1
    expression1 or expression2siendo similar y con los mismos inconvenientes / positivos que expression1 || expression2en javascriptJSDBroughton 18 de febrero de 2016 a las 13:05
  • 1
    Gracias, @selurvedu, puede ser confuso hasta que lo entiendas bien. Aprendí de la manera difícil, por lo que la tuya puede que no sea tan difícil. ;) Usar if sin el else, al final de una expresión generadora o comprensión de lista filtrará el iterable. En el frente, es una operación condicional ternaria y requiere el else. ¡¡Salud!! Aaron Hall 27 de mayo de 2016 a las 4:37
  • @AaronHall Aunque su uso de metasintáctico expressionNpara todas las instancias es consistente, podría ser más fácil de entender con nombres que distinguen 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? tchrist 26/01/19 a las 14:12
  • @tchrist gracias por la revisión: si miras el historial de revisiones, esta publicación tiene actualmente dos revisiones. La mayoría de mis otras respuestas, especialmente las principales, se han revisado una y otra vez. Esta respuesta nunca me llama la atención porque el estado de wiki de la comunidad no me da crédito por el contenido, por lo que nunca veo ningún voto sobre él. Como realmente no tengo tiempo para editar esto en este momento, Frog sabe cuándo volverá a llamar mi atención en el futuro. Puedo ver que ha editado la respuesta principal, así que siéntase libre de pedir prestado / citar mi material de esta publicación en esa (¡y citarme si es apropiado!)Aaron Hall 26/01/19 a las 18:24
26

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]()

producción:

'b greater than a'
4
  • 1
    ¿Por qué no simplemente result = (y, x)[a < b]¿Por qué utiliza la lambdafunción ? Grijesh Chauhan 27 de diciembre de 2013 a las 5:50
  • 6
    @GrijeshChauhan Porque en expresiones "compatibles", por ejemplo, que involucran una llamada a una función, etc., esto se ejecutaría en ambos casos. Puede que esto no sea necesario. glglgl 13/0214 a las 8:14
  • 1
    El uso de lambdafunciones es una exageración para esta preguntajocerfranquiz 14 de diciembre de 2020 a las 4:29
  • @GrijeshChauhan En resumen, esto implementa la llamada “ evaluación de cortocircuito ”. En general, P ? x : yo x if P else yse puede escribir como (lambda:y, lambda:x)[P](), pero dudo que tenga un mejor rendimiento y, por lo tanto, sea necesario. SneezeFor16Min 19 de enero a las 10:11
26
a if condition else b

Simplemente memorice esta pirámide si tiene problemas para recordar:

     condition
  if           else
a                   b 
0
26

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 quiere evitar la evaluación de yes() y no() , porque en

(no(), yes())[boolean]  # bad

ambos no()y yes()son evaluados.

24

El operador condicional ternario simplemente permite probar una condición en una sola línea reemplazando el if-else de varias líneas, lo que hace que el código sea compacto.

Sintaxis:

[on_true] if [expression] else [on_false]

1- Método simple para utilizar el 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 uso 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- El operador ternario se puede escribir como if-else anidado:

# 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
1
  • 1
    Tenga en cuenta que el operador ternario es más pequeño (en memoria) y más rápido que el anidado if. Además, su anidado if-elseno es en realidad una reescritura del operador ternario y producirá una salida diferente para los valores seleccionados de ayb (específicamente si uno es un tipo que implementa un __ne__método extraño ). Perkins 11 oct 2018 a las 17:28
22

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 que no sea 0 se evalúa como Verdadero.

Así es como funciona:

si la condición [condición] se convierte en "Verdadero", se evaluará expresión_1 pero no expresión_2. Si "y" algo con 0 (cero), el resultado siempre será rápido. 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 es necesario evaluar la expresión. Así es como funciona el propio compilador, en todos los lenguajes.

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 exp1que sería Verdadero cuando exp1 no es 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 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 ramificación que usa "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 lista vacía [] o cadena vacía ''.) Ya que si 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 esto: -

[condition] and ([expression_1] or 1) or [expression_2] ;

1
  • Si desea usar eso en el contexto de x = [condition] and ([expression_1] or 1) or [expression_2]y se expression_1evalúa como falso, xserá 1, no expression_1. Utilice la respuesta aceptada. moi 20/10/2017 a las 6:37
21

Más un consejo que una respuesta (no es necesario repetir lo obvio por centé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 considerarlo poco pitónico (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 atractivo visualmente en grandes bloques de código.

4
  • 7
    Prefiero print( 'yes' if conditionX else 'nah' )tu respuesta. :-)frederick99 20 de agosto de 2017 a las 6:07
  • Eso es si quieres print()en ambos casos, y parece un poco más pitónico, tengo que admitir :) Pero, ¿qué pasa si las expresiones / funciones no son las mismas, como print('yes') if conditionX else True, para obtener la print()única verdadconditionX Todor Minakov 26/10/2017 a las 11:40
  • Para agregar al comentario de Frederick99, otra razón para evitar print('yes') if conditionX else print('nah')es que da un SyntaxError en Python2. Thierry Lathuille 21 oct 2018 a las 21:51
  • La única razón por la que da un error de sintaxis es porque en Python 2 print es una declaración - print "yes", mientras que en Python 3 es una función - print("yes"). Eso se puede resolver usándolo como una declaración, o mejor - from future import print_function. Todor Minakov 22 oct 2018 a las 4:09
15

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 utilizar 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 se utiliza el ternario en los casos en que el cortocircuito sería suficiente.

0
14

La respuesta de Vinko Vrsalovic es suficientemente buena. Solo queda una cosa más:

Note that conditionals are an expression, not a statement. This means you can't use assignment statements or pass or other statements within a conditional expression

Operador de morsa en Python 3.8

Después de que se introdujo el operador de morsa en Python 3.8, algo cambió.

(a := 3) if True else (b := 5)

da a = 3y b is not defined,

(a := 3) if False else (b := 5)

da a is not definedy b = 5, y

c = (a := 3) if False else (b := 5)

da c = 5, a is not definedy b = 5.

Incluso si esto puede ser feo, las asignaciones se pueden realizar dentro de expresiones condicionales después de Python 3.8. De todos modos, es mejor usar una if declaración normal en este caso.

4
  • En el primer ejemplo: en (a := 3) if True else (b := 5)realidad es un primer operador de morsa redundante. Esto hará:a = 3 if True else (b := 5)Andrew Anderson 4 de agosto a las 12:48
  • 1
    @AndrewAnderson No, no es redundante. Debe comparar el primer y el segundo ejemplo. Puede combinarlos y considerar esto: (a := 3) if x else (b := 5)siempre obtiene uno ao basignado, no ambos. Sin embargo, considere a = 3 if x else (b := 5)cuándo x == Falseobtendrá a = 5y b = 5dónde se asignan ambos. Ddavid 5 de agosto a las 15:36
  • Si eso es correcto :). Consideré esto solo para el x=Truecaso que, por supuesto, es limitado. Andrew Anderson 6 de agosto a las 11:56
  • Debido a que realmente no escribimos este código if True else, la razón del primer ejemplo solo se compara con otros ejemplos. Ddavid 7 de agosto a las 12:30
11

Muchos lenguajes de programación derivados Csuelen tener la siguiente sintaxis de operador condicional ternario:

<condition> ? <expression1> : <expression2>

At first, the Python Benevolent Dictator For Life (I mean Guido van Rossum, of course) rejected it (as non-Pythonic style), since it's quite hard to understand for people not used to C language. Also, the colon sign : already has many uses in Python. After PEP 308 was approved, Python finally received its own shortcut conditional expression (what we use now):

<expression1> if <condition> else <expression2>

Entonces, primero evalúa la condición. Si regresa True, expression1 se evaluará para dar el resultado; de lo contrario , se evaluará expression2 . Debido a la mecánica de Lazy Evaluation , solo se ejecutará una expresión.

A continuación se muestran 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.

10

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")
4
  • He agregado un ejemplo de declaración de una línea para verificar qué número es grande para elaborarlo másrealmanusharma 21 oct 2018 a las 20:45
  • 1
    printrealmente no es una buena opción, ya que esto dará un SyntaxError en Python2. Thierry Lathuille 21 oct 2018 a las 21:52
  • @Thierry Lathuille aquí utilicé la función print () no la declaración de impresión, la función de impresión es para Python 3 mientras que la declaración de impresión es para Python 2realmanusharma 21 oct 2018 a las 21:54
  • La pregunta ya se ha hecho en SO, solo pruébelo con Python 2 y lo verá usted mismo. 'print (' hola ') es una sintaxis perfectamente válida en Python 2.7, pero la forma en que se analiza hace que el código anterior arroje un SyntaxError. Thierry Lathuille 21 oct 2018 a las 21:58
7

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 que hay un mejor idioma. Este es el escenario de usar un valor predeterminado.

Supongamos que queremos usar option_valuecon un valor predeterminado si no está configurado:

run_algorithm(option_value if option_value is not None else 10)

o, si option_valueno se establece en un valor Falsy ( 0, "", etc.), simplemente

run_algorithm(option_value if option_value else 10)

Sin embargo, en este caso, una solución cada vez mejor es simplemente escribir

run_algorithm(option_value or 10)
4
  • 3
    Un complemento valioso, pero no estoy de acuerdo: nooption_value or 10 es mejor que . Es más corto, de hecho, pero me parece extraño y puede dar lugar a errores. ¿Qué pasa si , por ejemplo? El primer fragmento se ejecutará porque no lo es . El segundo y tercer fragmentos, sin embargo, se ejecutarán porque es falso. Los dos fragmentos no son equivalentes y, por lo tanto, uno no es mejor que el otro. Y explícito es mejor que implícito. option_value if option_value is not None else 10option_value = 0run_algorithm(0)option_valueNonerun_algorithm(10)0ruancomelli 20/10/20 a las 15:21
  • @ruancomelli: Buen punto. Modifiqué la respuesta para reflejar esa corrección. user118967 22/10/20 a las 14:04
  • 4
    En cuanto a que se vea extraño, me pregunto si le pareció extraño porque notó la imprecisión (que en realidad no era equivalente). Para mí suena natural porque me recuerda decir en inglés: "Usa esto o aquello (si la primera opción no está disponible)". Pero, por supuesto, eso es subjetivo. Es útil saber que no parece natural para todos. user118967 22/10/20 a las 14:06
  • 2
    ¡Mucho mejor! Y gracias por la explicación sobre el "o" -idiom. Me parece extraño porque tiendo a pensar oren una función que asigna dos argumentos a un booleano, por lo que espero que devuelva Trueo False(esto sucede en muchos otros lenguajes de programación). Pero "use esto o aquello" es un buen nemotécnico y definitivamente me ayudará (y con suerte a otros) a recordar este patrón. ruancomelli 28/10/20 a las 19:44
6

Python tiene una forma ternaria para las asignaciones; sin embargo, puede haber incluso una forma más corta que la gente debería conocer.

Es muy común tener que 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 para realizar este tipo de asignaciones.

A continuación se muestra la forma ternaria. Pero esta no es la forma más concisa, vea el último ejemplo.

>>> a = li1 if li1 else li2
>>> 
>>> a
[1, 2, 3]
>>> 

Con Python, simplemente puede usarlo orpara asignaciones alternativas.

>>> a = li1 or li2
>>> 
>>> a
[1, 2, 3]
>>> 

Lo anterior funciona ya que li1es Noney la interpretación lo trata como falso en las expresiones lógicas. El interp luego avanza y evalúa la segunda expresión, que no es ni Nonees una lista vacía, por lo que se asigna a un.

Esto también funciona con listas vacías. Por ejemplo, si desea asignar acualquier lista que tenga elementos.

>>> li1 = []
>>> li2 = [1, 2, 3]
>>> 
>>> a = li1 or li2
>>> 
>>> a
[1, 2, 3]
>>> 

Sabiendo esto, puede simplemente realizar esas asignaciones cada vez que las encuentre. Esto también funciona con cadenas y otros iterables. Puede asignar ala cadena que no esté vacía.

>>> s1 = ''
>>> s2 = 'hello world'
>>> 
>>> a = s1 or s2
>>> 
>>> a
'hello world'
>>> 

Siempre me gustó la sintaxis ternaria de C, ¡pero Python va un paso más allá!

Entiendo que algunos puedan decir que esta no es una buena opción estilística porque se basa en mecánicas 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 aficionado. Pero cuanto más aprende y comprende la mecánica del sistema subyacente, más lo aprecia.

-1

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

-1

Encuentro engorrosa 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 (ayb), pero la sintaxis es mucho más clara para mí.

2
  • 3
    Esto parece ser el doble de trabajo, más uso de RAM y más ofuscado que la val = a if cond else bdeclaración más simple . eatsfood 28/04/20 a las 16:57
  • También ambos ay bser evaluados aquí cada vez, a diferencia de ena if cond else bRainer Koirikivi 11 de enero a las 13:22
-3

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
1
  • 1
    Si bien es útil para problemas similares, no es un condicional ternario. Funciona para reemplazar x if x else y, pero no x if z else y. Perkins 11/10/2018 a las 17:13
-3
is_spacial=True if gender = "Female" else (True if age >= 65 else False)

**

it can be nested as your need. best of luck

**