Pregunta ¿Python tiene un operador condicional ternario?


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


4427


origen


Respuestas:


Sí, lo era adicional en la versión 2.5.
La sintaxis es:

a if condition else b

primero condition es evaluado, luego a o b se devuelve en base a la Booleano valor de condition
Si condition evalúa a Cierto  a es devuelto, de lo contrario b es regresado.

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 un declaración. Esto significa que no puede usar asignaciones o pass u otras declaraciones en un condicional:

>>> pass if False else x = 3
  File "<stdin>", line 1
    pass if False else x = 3
          ^
SyntaxError: invalid syntax

En tal caso, debe usar un if declaración en lugar de un condicional.


Tenga en cuenta que es mal visto por algunos Pythonistas por varias razones:

  • El orden de los argumentos es diferente de muchos otros lenguajes (como C, Ruby, Java, etc.), lo que puede provocar errores cuando las personas que no están familiarizadas con el comportamiento "sorprendente" de Python lo utilizan (pueden revertir el orden).
  • Algunos lo encuentran "difícil de manejar", ya que va en contra del flujo normal de pensamiento (pensando en la condición primero y luego en los efectos).
  • Razones estilísticas

Si tiene problemas para recordar el orden, recuerde que si lo lee en voz alta, usted (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:


5285



Puede indexar en una tupla:

(falseValue, trueValue)[test]

test necesita regresar Cierto o Falso.
Puede ser más seguro implementarlo siempre como:

(falseValue, trueValue)[test == True]

o puedes usar el built-in bool() para asegurar una Booleano valor:

(falseValue, trueValue)[bool(<expression>)]

591



Para versiones anteriores a 2.5, está el truco:

[expression] and [on_true] or [on_false]

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

1. ¿Hay un equivalente del operador ternario "?:" De C?


245



expresión1 Si condición más expresión2

>>> a = 1
>>> b = 2
>>> 1 if a > b else -1 
-1
>>> 1 if a > b else -1 if a < b else 0
-1

155



De la documentación:

Las expresiones condicionales (a veces llamadas un "operador ternario") tienen la prioridad más baja de todas las operaciones de Python.

La expresion x if C else y primero evalúa la condición, do (no x); Si do es verdad, X se evalúa y se devuelve su valor; de otra manera, 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.


105



Se agregó un operador para una expresión condicional en Python en 2006 como parte de Propuesta de mejora de Python 308. Su forma difiere de la común ?: operador 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 la 2.5):

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

donde los operandos son perezosamente evaluado.

Otra forma es indexar una tupla (que no es coherente con el operador condicional de la mayoría de los otros idiomas):

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

o diccionario explícitamente construido:

result = {True: x, False: y}[a > b]

Otro (menos confiable), pero el método más simple es usar and y or operadores:

result = (a > b) and x or y

sin embargo, esto no funcionará si x sería False.

Una posible solución es hacer x y y listas 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


78



@arriba:

Desafortunadamente, el

(falseValue, trueValue)[test]

la solución no tiene un comportamiento de cortocircuito; por lo tanto, falseValue y trueValue se evalúan independientemente de la condición. Esto podría ser subóptimo o incluso con errores (es decir, tanto trueValue como falseValue podrían ser métodos y tener efectos secundarios).

Una solución a esto sería

(lambda: falseValue, lambda: trueValue)[test]()

(la ejecución se retrasa hasta que se conoce al ganador;)), pero introduce una incoherencia entre los objetos invocables y los no llamables. Además, no resuelve el caso cuando se usan propiedades.

Y así continúa la historia: elegir entre las tres soluciones mencionadas es una compensación entre tener la característica de cortocircuito, usar al menos Python 2.5 (en mi humilde opinión ya no es un problema) y no ser propenso a "trueValue-evalúa-a-falso" errores


72