Cómo utilizar goto

Cómo utilizar goto

A diferencia de otros lenguajes, Python no incluye una palabra reservada goto (del inglés go to, «ir a»), que permita realizar saltos a diversas porciones del código. Pero dada la flexibilidad del lenguaje, es posible implementar un operador de esta características utilizando python-goto. El módulo provee un decorador que emplea los módulos estándar dis y ctypes para reemplazar el byte-code generado por el intérprete e ingresar instrucciones de salto. Opera con las palabras label, para definir una determinada porción del código, y goto, para realizar el salto.

La instalación de python-goto es bien sencilla vía pip:

pip install python-goto

También puedes descargar manualmente el código de fuente e instalarlo vía python setup.py install o sencillamente copiar el archivo goto.py junto a tu programa.

Al momento de escribir este artículo (febrero de 2022), python-goto solo soporta hasta la versión 3.7 de Python. Su utilización en Python 3.8 o posterior probablemente resulte en un error.

Ahora bien, antes de ver cómo utilizar esta herramienta, recordemos cómo funciona goto en un lenguaje como C que soporta de forma nativa esta funcionalidad. El siguiente código solicita al usuario ingresar un número. Si se ingresa un valor no permitido (por ejemplo, una letra), se utiliza la instrucción goto para regresar al comienzo y volver a preguntar por el número.

int main(int argc, char *argv[])
{
    char input[10];
    int age;

get_input:  // Definición de la etiqueta (necesario para usar goto).
    printf("Ingresa tu edad: ");
    fgets(input, 10, stdin);
    age = atoi(input);
    if (age == 0) {
        // Si la edad no es válida, volvera la línea 6
        // donde está definida la etiqueta get_input.
        goto get_input;
    }
    printf("Tienes %d años.\n", age);

    return 0;
}

Una posible salida de este programa:

Ingresa tu edad: a
Ingresa tu edad: b
Ingresa tu edad: 30
Tienes 30 años.

Utilizando el módulo goto podemos replicar el código anterior en Python de la siguiente manera:

from goto import with_goto

@with_goto  # Decorador necesario.
def f():
    label .get_input  # Definir la etiqueta.
    age = input("Ingresa tu edad: ")
    try:
        age = int(age)
    except ValueError:
        goto .get_input  # Regresar a get_input.
    print("Tienes", age, "años.")

f()

¡Nada más sencillo! Si la entrada no puede ser convertida a un número, en la línea número 10 la ejecución regresa a la número 5, etiquetada con el nombre get_input.

Evítese usar las palabras label y goto para nombrar objetos, pues, como comenté anteriormente, son utilizados por el decorador. De lo contrario, se obtiene un error.

@with_goto  # Decorador necesario.
def f():
    label = 1
    label .get_input  # Definir porción del código.

Traceback (most recent call last):
    ...
SyntaxError: Unknown label 'get_input'

He aquí otro ejemplo donde se reimplementa la función incorporada range() usando goto:

from goto import with_goto

@with_goto
def range2(start, stop):
    i = start
    result = []

    label .begin
    if i == stop:
        goto .end

    result.append(i)
    i += 1
    goto .begin

    label .end
    return result

# Imprime [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(range2(1, 10))

Puedes conocer más sobre la implementación interna del módulo en el proyecto en GitHub.

Con todo, recuerda que la utilización de goto es considerada una mala práctica en la programación, razón por la cual Python no lo incluye en el lenguaje. Por lo general es más conveniente reemplazar esta herramienta con el uso de bucles y funciones.



4 comentarios.

  1. Hola y cómo salto hacia atrás sin un GOTO???
    Por ejemplo, para una vez terminado un program sensillo por ejemplo…Calcular el area de un cuadrado entrando po teclado los datos.
    Una vez calculada el area, poder ingrsar nuevos datos sin que tenga que correr de nuevo el programa..
    Esa es mi duda.
    Soy novato en PYTHON.
    Mi mayor experiencia fue en ASSEMBLER para 6800.
    Utilizaba JMP..Y BRANCH por ejemplo.
    Si alguien me puede sacar la duda.MUCHAS GRACIAS!

Deja una respuesta