Intercambio de valores rápido en Python

Cuando empecé a cursar Ingeniería en Sistemas en el año 2003, tuvimos una materia llamada Algoritmos y Estructuras de Datos. La semana del curso estaba compuesta por una clase teórica, una clase práctica y una clase “especial” dictada por un docente de apellido Marina que tenía como objetivo hacernos pensar resolviendo problemas; en las primeras clases ni siquiera programábamos.
El lenguaje de programación de la materia era C y en una de las clases, este docente recordaba risueño que un alumno había querido intercambiar el valor de dos variables

int a = 1;
int b = 2;

haciendo:

a = b;
b = a;

El error es evidente; en a se copia el valor contenido en b (2) pisando el valor original (1) y al ejecutarse la segunda sentencia, el nuevo valor de a (2) es copiado en b.

La siguiente tabla muestra los valores que van tomando las variables a y b:

La forma correcta de intercambiar los valores habría sido utilizando una variable auxiliar en la cual mantener uno de los valores:

int aux;
int a = 1;
int b = 2;
aux = a;
a = b;
b = aux;

La siguiente tabla muestra los valores que van tomando las variables aux, a y b:

Lo gracioso del asunto es que unos años más tarde conocí otro lenguaje de programación, Python.

En Python un tipo de dato que viene con el lenguaje es la tupla. Una tupla es una secuencia (sus elementos tienen orden) inmutable (no se puede cambiar su tamaño o contenido) que puede tener dentro objetos de distinto tipo. Un ejemplo de tupla en Python (contiene tres números y dos cadenas de texto):

(1, 2, "tres", 4, "Juan")

La forma de apuntar a ese objeto desde una variable es simplemente:

a = (1, 2, "tres", 4, "Juan")

Aunque podemos obviar los paréntesis y de todas formas funcionará. Decimos que la tupla es empaquetada:

a = 1, 2, "tres", 4, "Juan"

De forma similar, podemos desempaquetar la tupla en nuevas variables:

b, c, d, e, f = a

La condición es que el número de variables en el lado izquierdo del operador = coincida con el número de elementos en la tupla.

La siguiente sentencia, empaqueta y desempaqueta:

x, y, z = "Juan", 100, 1

Y es equivalente a:

x = "Juan"
y = 100
z = 1

Finalmente, esta propiedad del lenguaje nos permite intercambiar rápidamente los valores de 2 (o n) variables:

a = 1
b = 2
a, b = b, a


Así, lo que un alumno despistado quiso hacer en 2 sentencias y Marina mostró que se hacía correctamente en 3, yo lo hago en 1 :)

About Juanjo

Mi nombre es Juanjo Conti, vivo en Santa Fe y soy Ingeniero en Sistemas de Información. Mi lenguaje de programación de cabecera es Python; lo uso para trabajar, estudiar y jugar. Como hobby escribí un libro de cuentos que se puede descargar gratuitamente.
This entry was posted in Aprendiendo Python, Humor, Problemas and tagged , . Bookmark the permalink.
  • http://www.davidcapello.com.ar/ David Capello

    Como siempre, si le sacan el cuero a C, mi comentario malicioso no puede faltar :)

    Internamente Python hace lo mismo que C, sólo que nadie lo nota debido al manejo especial que tiene Python con el operador = al usar tuplas. Eso es lo bueno (y lo malo) de C: no te esconde nada, las instrucciones tienen una relación directa con el hardware. Eso es lo malo (y bueno) en Python: no sabes si se creo una tupla temporal, o cómo hizo exactamente el cambio de valores, abstrae la operación de tal forma que el programador no tiene de qué preocuparse.

    En C++ existe la función std::swap, que te permite intercambiar variables de cualquier tipo (inclusive vectores, y tuplas de C++0x). Y es una línea de código también ;P

    int a = 1;
    int b = 2;
    swap(a,b);

  • Juanjo

    El título de este post debería haber sido “Intercambio compacto…”

  • http://blog.tordek.com.ar Tordek

    Y yo te ofrezco uno más lindo para C:

    int a = 1
    int b = 2
    a ^= b ^= a ^= b

    http://www.codeproject.com/KB/tips/stupidxortrick.aspx?display=PrintAll&fid=4560&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=51 << Explicación
    aunque no funca si a==b.

  • Diego Mascialino

    La primer tabla está incorrecta (la última fila debería ser 2, 2), y en la segunda te falta la variable aux.

    Saludos
    Diego

  • http://nacho.larrateguy.com.ar Nacho

    Totalmente de acuerdo con el comentario de David. Sólo una abstracción. Quizá más fácil de leer (porque usa el operador de asignación).

  • Juanjo

    Tordek! Esa si que no la conocía.

  • Juanjo

    Diego, gracias por la corrección, con el apuro subí cualquier imagen. Corregido!

  • http://blog.tordek.com.ar Tordek

    Más rápido que usar una variable, porque no necesitás pedir memoria, assembler:

    mov ax, 1;
    mov bx, 5;
    push ax;
    mov ax, bx;
    pop bx;

    :P

    Optimizar rocks ;)