Publi

Píldora: Operador ternario en Python y en C (con ejemplos)

Operador ternario en Python

En programación, hay un momento en el que descubres ciertas técnicas. Y, a partir de ese momento, ya no puedes vivir sin ellas. Eso me sucedió con el operador ternario. Esta estructura nos permite ahorrar código, lo que significa escribir menos líneas y hacerlas más sencillas. Tomaremos tres argumentos, uno de ellos será una condición y los otros dos serán valores (llamémosles a y b). Básicamente, puede solucionar una situación muy común:

Si condición se cumple, la variable c = a. Si no se cumple, la variable c = b

En lenguaje C y derivados

Esto, en lenguajes como C, y cualquier otro que herede parte de su sintaxis, como C++, PHP, Java, Javascript, C#, Swift y muchos más, podemos hacerlo con ?: de la siguiente forma:

1
variable = (condicion)?valor_si:valor_no;

Por supuesto donde digo condición, podemos poner todas las condiciones que queramos, resultado de funciones o cualquier cosa que me pueda devolver un valor verdadero o falso.

Por ejemplo, podemos tener este código (por poner algo funcional):

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

int main()
{
  int mayor, a=10, b=12;

  mayor = (a>b)?a:b;

  printf ("El mayor es: %d\n", mayor);
}

Aunque no estamos limitados a asignación de variables, podríamos por ejemplo hacer lo siguiente:

1
2
3
4
5
6
7
8
#include <stdio.h>

int main()
{
  int a=10, b=12;

  printf ("El mayor es: %d\n", (a>b)?a:b);
}

Podemos incluso, hacer llamadas a funciones dependiendo de si se cumple o no la condición:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

int funcion1()
{
  printf ("Has llamado a la funcion 1\n");
}

int funcion2()
{
  printf ("Has llamado a la funcion 2\n");
}

int main()
{
  int a=10, b=12;

  ((a>b)?funcion1:funcion2)();
}

En este último ejemplo es importante el paréntesis que rodea a la expresión, ya que el resultado de (a>b)?funcion1:funcion2 es lo que tiene que ejecutarse. En definitiva, esto tiene muchas posibilidades y podemos usarlo de muchas maneras. Aunque la evaluación de la expresión siempre será de la misma manera.

El caso de Python

Empecé con Python hace algo menos de un año gracias a unas charlas organizadas por Linux Málaga. Desde el primer momento a mí me picó la curiosidad de cómo utilizar el operador ternario o, al menos, simular su comportamiento. Es un lenguaje con mucha potencia, sencillo, y capaz de hacer muchas cosas con poco código. Así que, ¿por qué andarnos repitiendo código para estas cosas?

Es cierto que muchos desarrolladores no lo consideran demasiado pitónico, aunque yo no lo creo así. Y, como siempre, en Python, tenemos varias formas de hacer las cosas, aprovechándonos de su flexibilidad.

Expresiones condicionales

Esta forma, válida desde Python 2.5 (Septiembre de 2006) utiliza if y else. Lo raro, es que el orden de los elementos difiere un poco del operador ?:. En este caso es:

1
resultado = valor_si if condicion else valor_no

Podemos hacer algo como esto. Que nos imprimirá el número introducido sólo si es mayor a 50, si no, imprimirá 0 (aunque utilizar input sea algo inseguro para hacer un ejemplo vale):

1
2
3
c = input("Introduce un número: ")
r = c if (c>50) else 0
print(r)

Como en los ejemplos anteriores de C, podremos utilizarlo incluso para hacer llamadas a funciones:

1
2
3
4
5
6
7
8
def func_si():
    print ("SIIIIIUUUU")

def func_no():
    printf ("NOOOOOOU")

respuesta = raw_input('Introduzca "si" o cualquier otra cosa.')
func_si() if (respuesta=='si') else func_no()

E incluso lo podemos utilizar para asignar varios valores a varias variables al mismo tiempo. En el ejemplo lo hacemos en función de un valor pseudo-aleatorio entre 0 y 100:

1
2
3
import random
(a,b,c,d) = (1,2,3,4) if (random.randint(0,100)>50) else (4,3,2,1)
print (a,b,c,d)

Utilizando tuplas

Aunque, podemos escoger otra forma de hacer las cosas. En Python, es muy cómodo crear tuplas, o listas ordenadas de elementos. Así que podríamos coger una lista de dos elementos (uno para cuando se cumple la condición y otro para cuando no se cumple) y dado que True es 1 y False es 0, escoger la posición en función del cumplimiento de la condición.
Para no liarnos mucho, aquí va el código:

1
2
3
a = 10
b = 12
mayor = (b, a)[a>b]

Lo primero que nos puede chocar de este enfoque es que hay que invertir el orden de los valores. Es decir, el primer valor que ponemos es el que obtendremos cuando no se cumpla la condición, y el segundo será cuando sí se cumpla. Ya que, cuando no se cumple, el valor obtenido al evaluar la condición es False, que equivale a 0. Y cuando sí que se cumple, obtendremos True, que equivale a 1.
Por otro lado, tendremos un comportamiento ligeramente diferente a la hora de realizar la evaluación. Lo primero que hacemos es rellenar la tupla, por lo que estaremos escribiendo en memoria los dos valores resultantes. El problema de esto, es que:

  • Si los valores son muy grandes ocuparemos mucha memoria, porque tenemos que almacenar los dos.
  • Si b y a son llamadas a funciones, se llamará a las funciones antes de evaluar la condición, por lo que gastaremos tiempo de CPU innecesariamente.

Podemos ver este ejemplo más claro:

1
2
3
4
5
6
7
8
9
10
11
12
import random

def diez():
    print ("EJECUTAMOS DIEZ")
    return 10

def doce():
    print ("EJECUTAMOS DOCE")
    return 12

mayor = (diez(), doce())[(random.randint(0,100)>50)]
print(mayor)

Si ejecutamos este código veremos cómo se imprimen en pantalla los mensajes de las funciones diez() y doce() cuando en realidad deberíamos ver sólo uno, generado cuando, tras evaluar la posición de la tupla se escoja un elemento. Imaginemos que las funciones diez() y doce() pueden llevar a ser muy lentas o, que realizan cambios incompatibles en una base de datos y sólo debemos ejecutar una de ellas.

Para solucionar esto, podemos utilizar lambdas, haciendo la condición de la siguiente forma:
Para no liarnos mucho, aquí va el código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
a = 10
b = 12
mayor = (lambda:b, lambda:a)[a>b]()
[cc]

De esta forma creamos funciones anónimas que evaluaremos (para eso el () final) cuando escojamos el elemento en función de la condición. El código anterior quedaría así:
[cc lang="python"]
import random

def diez():
    print ("EJECUTAMOS DIEZ")
    return 10

def doce():
    print ("EJECUTAMOS DOCE")
    return 12

mayor = (lambda:diez(), lambda:doce())[(random.randint(0,100)>50)]()
print(mayor)

Con diccionarios, lambdas y a lo loco

Para completar aún más esto, podemos poner en orden los valores. Es decir, si estamos acostumbrados a poner primero el valor a devolver cuando la condición se cumple y luego el otro, podemos utilizar un diccionario (o en el ejemplo anterior ponerle un not a la condición). Y para que no se evalúe todo antes de la condición, también utilizar lambdas:

1
2
3
4
5
6
7
8
9
10
11
12
import random

def diez():
    print ("EJECUTAMOS DIEZ")
    return 10

def doce():
    print ("EJECUTAMOS DOCE")
    return 12

mayor = {True:lambda:doce(), False:lambda:diez()}[(random.randint(0,100)>50)]()
print(mayor)

¿Más formas?

Python da mucho juego. Por ejemplo, podemos utilizar booleanos para conseguir el mismo efecto. De forma que hagamos:

1
mayor = ((a>b) and [a] or [b])[0]

En este caso, devolveríamos a cuando se cumpla la condición y en caso contrario b. Podríamos, no hacer la lista [] con un elemento solo. Si os fijáis creamos una lista que sólo contenga a y una lista que sólo contenga b. Y al final, elegimos el primer elemento de esas listas, que sería a o b. Podríamos simplificarlo haciendo:

1
mayor = (a>b) and a or b

Aunque si el valor de a es False, 0 o None, mayor será igual a b. Por lo que el comportamiento puede que no sea el deseado. Metiendo los elementos en listas salvaríamos el problema.

Operador Elvis

Operator Elvis. Elvis Operator
Y como ?: parece el emoticono de Elvis, o eso dicen. Tenemos el operador Elvis, derivado del ternario. Que nos hará la vida un poco más fácil en algunos lenguajes del estilo C (en C o C++ no todos los compiladores lo soportan porque no forma parte del lenguaje C). El operador Elvis también se llama operador condicional nulo, o Null Conditional Operator.

Este operador funciona así:

1
resultado = valor_1 ?: valor_2;

En este caso, resultado valdrá valor_1, siempre y cuando valor_1 no sea algo falso, como 0, nulo, etc, en ese caso, resultado valdrá valor_2. Es muy útil para establecer valores por defecto a variables. O cuando en C un puntero debe apuntar necesariamente a un objeto o función y ésta tiene valor NULL. Por ejemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>

void spanish()
{
  printf ("Hola!\n");
}

void english()
{
  printf ("Hello\n");
}

void french()
{
  printf ("Salut!\n");
}

void saluda(void (*idioma)())
{
  printf ("Te voy a saludar\n");
  (idioma?:&english)();
}

int main()
{
  saluda(&spanish);
  saluda(&french);
  saluda(NULL);
}

En este caso, saluda() llamará a una función según el idioma deseado. Pero el idioma podría ser NULL, y cuando vale NULL, se tomará el idioma inglés. Para eso evaluamos:

1
  (idioma?:&english)();

Haciendo que se llame a idioma si no vale NULL, y si éste es NULL, llamaremos a la función english().

En otros lenguajes como PHP nos puede servir por ejemplo para determinar el nombre de usuario conectado.

1
2
<?php
$userName = $currentUser['userName'] ?: 'invitado';

En este caso, si el nombre de usuario no existe en mi variable $currentUser, cogeremos de nombre de usuario ‘invitado’

¿Y en Python?

Ya que estábamos hablando de Python. En dicho lenguaje no tenemos este operador, como tampoco teníamos el ternario. Pero podríamos simular su comportamiento de la siguiente manera:

1
userName = currentUser['userName'] or 'invitado'

Lo que hacemos es utilizar el operador or que evaluará a verdadero siempre que, al menos uno de los dos extremos sea verdadero. Siguiendo esta norma, primero evalua currentUser[‘userName’], si esto tiene un valor que no sea falso, nos quedamos ahí y lo devolvemos como userName, pero si no, devolveremos ‘invitado’ que sí que es un valor que no es falso (es una cadena con contenido). Si los dos extremos son falsos, ya sí que userName será falso.

Incorpóralo en tus programas

Seguro que a partir de ahora empezarás a utilizar tanto el operador ternario, como el operador Elvis. O buscarás en tu lenguaje de programación el mismo comportamiento. Me encantaría ver comentarios con vuestros ejemplos.
Foto principal: Tom Parsons

También podría interesarte....

There are 25 comments left Ir a comentario

  1. Pingback: Píldora: Operador ternario en Python y en C (con ejemplos) | PlanetaLibre /

  2. carlos /
    Usando Mozilla Firefox Mozilla Firefox 61.0 en Ubuntu Linux Ubuntu Linux

    Le veo mucha utilidad a la hora de compactar el código, aunque a veces puede ser un poco difícil de leer, son pequeños detalles

    //0 = En curso; 1 = Ganador; 2 = Perdedor
    int estado = (suma == 7 || suma == 11) ? 1 : (suma == 2 || suma == 3 || suma == 12) ? 2 : 0;
    int punto = (estado == 0) ? suma : 0;

    1. Gaspar Fernández / Post Author
      Usando Mozilla Firefox Mozilla Firefox 61.0 en Ubuntu Linux Ubuntu Linux

      Bueno, es cuestión de pillarle el truco. A veces, para mejorar la legibilidad un paréntesis ayuda muchísimo aunque sea implícito y no haga falta.

      1. sota /
        Usando Google Chrome Google Chrome 81.0.4044.138 en Windows Windows NT

        aunque siempre esta bien el tener una lista, con la que guiarse xddddddd

  3. nicolasprominer2014@hotmail.com /
    Usando Google Chrome Google Chrome 79.0.3945.88 en Windows Windows 7

    xd

    1. sota /
      Usando Google Chrome Google Chrome 81.0.4044.138 en Windows Windows NT

      xd

  4. sota /
    Usando Google Chrome Google Chrome 81.0.4044.138 en Windows Windows NT

    Muy interesante el contenido xd , gracias , saludosssssss

  5. sota /
    Usando Google Chrome Google Chrome 81.0.4044.138 en Windows Windows NT

    xd

  6. Connections Unlimited /
    Usando Mozilla Firefox Mozilla Firefox 117.0 en Windows Windows NT

    If you are in the market for construction equipment, then you can save money in your budget by deciding to go with used construction equipment. Used construction equipment can be just as dependable as the brand new construction equipment, but it will cost you a lot less money in the end.

  7. OKBet /
    Usando Google Chrome Google Chrome 118.0.0.0 en Windows Windows NT

    We have a site for sports games. You must be interested. Valorant

  8. ufabet168 /
    Usando Google Chrome Google Chrome 107.0.0.0 en Windows Windows NT

    I am really inspired with your writing skills as well as with the format in your blog. Is that this a paid subject or did you customize it yourself? Either way keep up the excellent high quality writing, it’s uncommon to peer a great weblog like this one nowadays. ufabet168

  9. Marco /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    Great to see your enthusiasm for the ternary operator! It’s indeed a powerful and concise tool for streamlining code.

  10. Rank Xone /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    Online casinos are a game-changer. The convenience of playing from home without sacrificing the excitement of a traditional casino is unbeatable. 우리카지노

  11. Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    Your post is very helpful and information is reliable. I am satisfied with your post. Thank you so much for sharing this wonderful post.

  12. SimonWhitehead /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    Hey! Good stuff, do tell us when you finally post something like this! Frp Wall Panels

  13. SimonWhitehead /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    Hello – I must say, I am impressed with your site. I had no trouble navigating through all the tabs and information was very easy to access. I found what I wanted in no time at all. Pretty awesome. Would appreciate it if you add forums or something, it would be a perfect way for your clients to interact. Great job fc augsburg vereinsprofil

  14. SimonWhitehead /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    Wow! Such an amazing and helpful post this is. I really really love it. It’s so good and so awesome. I am just amazed. I hope that you continue to do your work like this in the future also tradesviz avis

  15. Thots lifestyle /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    Great post thanks for share Thots lifestyle

  16. Eurodreams /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    Datos realmente interesantes. Les mandamos cordial saludo desde la web donde comprobar Eurodreams hoy con los resultados de todos los sorteos celebrados de esta nueva lotería de Europa. Más información en Eurodreams hoy

  17. Cyber Global /
    Usando Google Chrome Google Chrome 122.0.0.0 en Windows Windows NT

    Great post! For more insights on related topics, check out Cyber Global ( https://www.cyberglobal.in ). We provide valuable resources on a wide range of subjects. Looking forward to more engaging content from you!

  18. TR SKIN /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    I like this blog. Thank you for sharing this information.

  19. Stats N Data /
    Usando Google Chrome Google Chrome 122.0.0.0 en Windows Windows NT

    Great post! For unparalleled market insights and research resources tailored specifically to the market research industry, explore Stats N Data (https://www.statsndata.org). Our platform offers invaluable market intelligence across diverse domains, empowering businesses with actionable insights that drive success. Looking forward to more engaging content from you!

  20. faraz /
    Usando Google Chrome Google Chrome 122.0.0.0 en Windows Windows NT

    It is a really good and useful bit of information. I appreciate you giving us this useful information. Kindly keep us informed in this manner.I appreciate you sharing.

  21. faraz /
    Usando Google Chrome Google Chrome 122.0.0.0 en Windows Windows NT

    I appreciate you giving us this useful information. Kindly keep us informed in this manner.I appreciate you sharing.

  22. syed jalal /
    Usando Google Chrome Google Chrome 122.0.0.0 en Windows Windows NT

    Kindly keep us informed in this manner. I appreciate you sharing.

Leave a Reply