Si Python no tiene un operador condicional ternario, ¿es posible simular uno usando otras construcciones de lenguaje?
6048
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:
En primer lugar
condition
se evalúa, a continuación, exactamente uno de cualquieraa
ob
se evalúa y volvió basa en la booleana valor decondition
. Si secondition
evalúa comoTrue
, entoncesa
se evalúa y se devuelve perob
se ignora, o bien cuandob
se evalúa y se devuelve peroa
se ignora.Esto permite un cortocircuito porque cuando
condition
es verdadero soloa
se evalúa yb
no se evalúa en absoluto, pero cuandocondition
es falso solob
se evalúa ya
no se evalúa en absoluto.Por ejemplo:
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 :Sin embargo, puede usar expresiones condicionales para asignar una variable así:
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 comox will be 4 if b is greater than 8 otherwise 9
.Documentación oficial:
fuente
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
. Six=2
yy=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)
oz = (x if x < y else y) + 3
)Puedes indexar en una tupla:
test
necesita devolver verdadero o falso .Puede ser más seguro implementarlo siempre como:
o puede usar el incorporado
bool()
para asegurar un valor booleano :fuente
(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>)]
. Labool()
función ha existido desde v2.2.1.True
yFalse
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:
Puede dar resultados incorrectos cuando
on_true
tiene un valor booleano falso. 1Aunque tiene el beneficio de evaluar las expresiones de izquierda a derecha, lo cual es más claro en mi opinión.
1. ¿Existe un equivalente del operador ternario "?:" De C?
fuente
<expression 1> if <condition> else <expression 2>
fuente
De la documentación :
Nuevo desde la versión 2.5.
fuente
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:que es equivalente a:
Aquí hay un ejemplo:
Otra sintaxis que se puede usar (compatible con versiones anteriores a 2.5):
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):
o diccionario construido explícitamente:
Otro método (menos confiable) pero más simple es usar
and
yor
operadores:Sin embargo, esto no funcionará si
x
lo fueraFalse
.Una posible solución es crear
x
yy
enumerar o tuplas como se muestra a continuación:o:
Si está trabajando con diccionarios, en lugar de usar un condicional ternario, puede aprovechar
get(key, default)
, por ejemplo:Fuente: ?: En Python en Wikipedia
fuente
result = {1: x, 0: y}[a > b]
es otra variante posible (True
y enFalse
realidad son enteros con valores1
y0
)Desafortunadamente, el
la solución no tiene comportamiento de cortocircuito; así ambos
falseValue
ytrueValue
se evalúan independientemente de la condición. Esto podría ser subóptimo o incluso defectuoso (es decir, ambostrueValue
yfalseValue
podrían ser métodos y tener efectos secundarios).Una solución a esto sería
(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" .fuente
if else if
.Operador ternario en diferentes lenguajes de programación
Aquí solo trato de mostrar alguna diferencia importante
ternary operator
entre un par de lenguajes de programación.fuente
Para Python 2.5 y posteriores hay una sintaxis específica:
En Python anteriores, no se implementa un operador ternario, pero es posible simularlo.
Sin embargo, existe un problema potencial, que si se
cond
evalúaTrue
y seon_true
evalúaFalse
,on_false
se devuelve en lugar deon_true
. Si desea este comportamiento, el método es correcto; de lo contrario, use esto:que puede ser envuelto por:
y usado de esta manera:
Es compatible con todas las versiones de Python.
fuente
q("blob", on_true, on_false)
retornoson_false
, mientras queon_true if cond else on_false
retornoson_true
. Una solución consiste en reemplazarcond
concond is not None
en estos casos, aunque eso no es una solución perfecta.bool(cond)
lugar decond is True
? El primero verifica la veracidad decond
, el segundo verifica la igualdad de puntero con elTrue
objeto. Como lo destacó @AndrewCecil,"blob"
es verdad perois not True
.[on_false, on_True][cond is True]
para que la expresión se acorte.A menudo puedes encontrar
pero esto lleva a un problema cuando on_true == 0
donde esperarías para un operador ternario normal este resultado
fuente
Si. Del archivo de gramática :
La parte de interés es:
Entonces, una operación condicional ternaria tiene la forma:
expression3
será evaluado perezosamente (es decir, evaluado solo siexpression2
es falso en un contexto booleano). Y debido a la definición recursiva, puede encadenarlos indefinidamente (aunque puede considerarse un mal estilo).Una nota sobre el uso:
Tenga en cuenta que cada
if
debe seguirse con unelse
. 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: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: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 resultarle algo doloroso escribir lo siguiente:
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 utilizaror
el comportamiento de acceso directo: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.
fuente
expression1 or expression2
ser similar y con los mismos inconvenientes / positivos queexpression1 || expression2
en JavaScriptexpressionN
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
salida:
fuente
result = (y, x)[a < b]
qué utiliza lalambda
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.
Sintaxis:
1- Método simple para usar operador ternario:
2- Método directo de uso de tuplas, diccionario y lambda:
3- El operador ternario se puede escribir como anidado if-else:
El enfoque anterior se puede escribir como:
fuente
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.
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, emptyString 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", 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,
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
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
La segunda expresión exp2 no se evaluará, ya
True and exp1
que sería True cuando exp1 no sea falso.Similarmente en
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] ;
fuente
x = [condition] and ([expression_1] or 1) or [expression_2]
y seexpression_1
evalúa como falso,x
será1
, noexpression_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:
, se convierte en:
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.
fuente
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 - comoprint('yes') if conditionX else True
- para conseguir laprint()
ú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ónprint("yes")
. Eso se puede resolver ya sea usándolo como una declaración, o mejor -from future import print_function
.Simplemente memorice esta pirámide si tiene problemas para recordar:
fuente
Una de las alternativas a la expresión condicional de Python.
es el siguiente:
que tiene la siguiente extensión agradable:
La alternativa más corta sigue siendo:
pero no hay alternativa a
si quieres evitar la evaluación de
yes()
yno()
, porque enambos
no()
yyes()
son evaluados.fuente
Muchos lenguajes de programación derivados
C
generalmente tienen la siguiente sintaxis de operador condicional ternario: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):
Los operadores ternarios se pueden encadenar en serie:
El siguiente es el mismo que el anterior:
Espero que esto ayude.
fuente
Como ya se respondió, sí, hay un operador ternario en python:
Información Adicional:
Si
<expression 1>
es la condición, puede usar la evaluación de cortocircuito :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.
fuente
short-circuit
evaluación.SÍ, Python tiene un operador ternario, aquí está la sintaxis y un código de ejemplo para demostrar lo mismo :)
fuente
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.
^ 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.
Con Python, simplemente puede usar
or
para tareas alternativas.Lo anterior funciona como
li1
esNone
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 esNone
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.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.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á.
fuente
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:o simplemente
Sin embargo, una solución cada vez mejor es simplemente escribir
fuente
si la variable está definida y desea verificar si tiene valor, puede simplemente
a or b
saldrá
fuente
x if x else y
, pero nox if z else y
.Una forma ordenada de encadenar múltiples operadores:
fuente
Encuentro engorroso la sintaxis predeterminada de Python
val = a if cond else b
, así que a veces hago esto:Por supuesto, tiene la desventaja de evaluar siempre ambos lados (a y b), pero la sintaxis es mucho más clara para mí.
fuente
val = a if cond else b
declaración más simple .** **
** **
fuente