¿Python tiene un operador condicional ternario?



Answers

Puede indexar en una tupla:

(falseValue, trueValue)[test]

test debe ser True o False .
Puede ser más seguro implementarlo siempre como:

(falseValue, trueValue)[test == True]

o puede usar el bool() incorporado bool() para asegurar un valor Boolean :

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

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




Para Python 2.5 y posterior hay una sintaxis específica:

[on_true] if [cond] else [on_false]

En las Pythons más antiguas, 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 evalúa como True y on_true evalúa como False , se devuelve on_true 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.




Se agregó un operador para una expresión condicional en Python en 2006 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 la 2.5):

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

donde los operandos son evaluados perezosamente .

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 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 sería False .

Una solución posible es hacer listas y , 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 utilizar un condicional ternario, puede aprovechar get(key, default) , por ejemplo:

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

Fuente: ?:




¿Python tiene un operador condicional ternario?

Sí. 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 es de la forma:

expression1 if expression2 else expression3

expression3 se evaluará de forma diferida (es decir, se evaluará solo si expression2 es falso en un contexto booleano). Y debido a la definición recursiva, puede encadenarlos indefinidamente (aunque puede considerarse un estilo incorrecto).

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

Una nota sobre el uso:

Tenga en cuenta que cada if debe seguir con un else . Las personas que aprenden listas de comprensión y expresiones de generador 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 un else:

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

que genera un SyntaxError: invalid syntax . Por lo tanto, lo anterior es una pieza incompleta de la lógica (quizás el usuario espera una no operación en la condición falsa) o lo que puede ser intencionado es usar expression2 como un filtro - señala que el siguiente es legal Python:

[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.

Sintaxis alternativa para un caso más estrecho:

Puede encontrar algo doloroso escribir lo siguiente:

expression1 if expression1 else expression2

expression1 deberá evaluarse dos veces con el uso anterior. Puede limitar la redundancia si es simplemente una variable local. Sin embargo, una expresión idiomática común y performante para este caso de uso es usar or el comportamiento de atajo:

expression1 or expression2

que es equivalente en semántica. Tenga en cuenta que algunas guías de estilo pueden limitar este uso sobre la base de la claridad; sintetiza una gran cantidad de significado en muy poca sintaxis.




expresión1 si condición else 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



Hay una opción ternaria como se indica en otras respuestas, pero también puede simularla usando "o" si está marcando contra un valor booleano o Ninguno:

>>> a = False
>>> b = 5
>>> a or b
5

>>> a = None
>>> a or b
5



In [1]: a = 1 if False else 0

In [2]: a
Out[2]: 0

In [3]: b = 1 if True else 0

In [4]: b
Out[4]: 1



Más un consejo que una respuesta (no es necesario que repita 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 como unpythonic (incluso, ruby-ish :), pero personalmente lo encuentro más natural, es decir, cómo lo expresarías normalmente, y un poco más atractivo visualmente en grandes bloques de código.




A menudo puede 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 se esperaría que 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



Sí.

>>> b = (True if 5 > 4 else False)
>>> print b
True



Related