when - python if==
¿Hay una etiqueta/goto en Python? (14)
¿Hay un goto
o equivalente en Python que pueda saltar a una línea específica de código?
Ahora está. ir
Creo que esto podría ser útil para lo que estás buscando.
En Python, la instrucción goto es compatible con goto .<label_name>
y label .<label_name>
. Para obtener más información, vaya a este enlace .
def func():
resp = call_something()
if resp != 0: # Failure case
goto .failure_handler
....
....
resp = ....
if resp != 0: # Failure case
goto .failure_handler
....
....
label .failure_handler
cleanup
return -1
En general, en todo el planeta, las personas recomiendan evitar el uso de la declaración goto. Pero un manejo de fallas en una función puede manejarse bien solo con la sentencia goto. Incluso yo no prefiero el uso de goto que no sea controlador de fallas.
Encontré esto en las preguntas frecuentes oficiales de diseño e historia de python .
¿Por qué no hay goto?
Puede usar excepciones para proporcionar un "goto estructurado" que incluso funciona a través de llamadas a funciones. Muchos piensan que las excepciones pueden emular convenientemente todos los usos razonables de las construcciones "go" o "goto" de C, Fortran y otros lenguajes. Por ejemplo:
class label(Exception): pass # declare a label
try:
...
if condition: raise label() # goto label
...
except label: # where to goto
pass
...
Esto no le permite saltar en el medio de un bucle, pero de todos modos se considera un abuso de goto. Utilizar con moderación.
Es muy bueno que esto se mencione incluso en las preguntas frecuentes oficiales, y que se proporcione una buena muestra de solución. Realmente me gusta Python porque su comunidad se está tratando incluso así goto
Es técnicamente factible agregar una declaración tipo ''goto'' a python con algo de trabajo. Usaremos los módulos "dis" y "nuevo", ambos muy útiles para escanear y modificar el código de byte de Python.
La idea principal detrás de la implementación es marcar primero un bloque de código como usar declaraciones "goto" y "label". Se usará un decorador especial "@goto" para marcar funciones "goto". Luego escaneamos ese código para estas dos declaraciones y aplicamos las modificaciones necesarias al código de bytes subyacente. Todo esto sucede en el momento de compilar el código fuente.
import dis, new
def goto(fn):
"""
A function decorator to add the goto command for a function.
Specify labels like so:
label .foo
Goto labels like so:
goto .foo
Note: you can write a goto statement before the correspnding label statement
"""
labels = {}
gotos = {}
globalName = None
index = 0
end = len(fn.func_code.co_code)
i = 0
# scan through the byte codes to find the labels and gotos
while i < end:
op = ord(fn.func_code.co_code[i])
i += 1
name = dis.opname[op]
if op > dis.HAVE_ARGUMENT:
b1 = ord(fn.func_code.co_code[i])
b2 = ord(fn.func_code.co_code[i+1])
num = b2 * 256 + b1
if name == ''LOAD_GLOBAL'':
globalName = fn.func_code.co_names[num]
index = i - 1
i += 2
continue
if name == ''LOAD_ATTR'':
if globalName == ''label'':
labels[fn.func_code.co_names[num]] = index
elif globalName == ''goto'':
gotos[fn.func_code.co_names[num]] = index
name = None
i += 2
# no-op the labels
ilist = list(fn.func_code.co_code)
for label,index in labels.items():
ilist[index:index+7] = [chr(dis.opmap[''NOP''])]*7
# change gotos to jumps
for label,index in gotos.items():
if label not in labels:
raise Exception("Missing label: %s"%label)
target = labels[label] + 7 # skip NOPs
ilist[index] = chr(dis.opmap[''JUMP_ABSOLUTE''])
ilist[index + 1] = chr(target & 255)
ilist[index + 2] = chr(target >> 8)
# create new function from existing function
c = fn.func_code
newcode = new.code(c.co_argcount,
c.co_nlocals,
c.co_stacksize,
c.co_flags,
''''.join(ilist),
c.co_consts,
c.co_names,
c.co_varnames,
c.co_filename,
c.co_name,
c.co_firstlineno,
c.co_lnotab)
newfn = new.function(newcode,fn.func_globals)
return newfn
if __name__ == ''__main__'':
@goto
def test1():
print ''Hello''
goto .the_end
print ''world''
label .the_end
print ''the end''
test1()
Espero que esto responda la pregunta.
Estaba buscando algo similar a
for a in xrange(1,10):
A_LOOP
for b in xrange(1,5):
for c in xrange(1,5):
for d in xrange(1,5):
# do some stuff
if(condition(e)):
goto B_LOOP;
Así que mi enfoque era usar un booleano para ayudar a salir de los bucles for anidados:
for a in xrange(1,10):
get_out = False
for b in xrange(1,5):
if(get_out): break
for c in xrange(1,5):
if(get_out): break
for d in xrange(1,5):
# do some stuff
if(condition(e)):
get_out = True
break
Las etiquetas para break
y continue
se propusieron en PEP 3136 en 2007, pero fueron rechazadas. La sección Motivation de la propuesta ilustra varios métodos comunes (si bien poco elegantes) para imitar break
etiquetadas en Python.
No, Python no admite etiquetas y goto, si eso es lo que buscas. Es un lenguaje de programación (altamente) estructurado.
Para responder la ascobol @bobince
usando la sugerencia de @bobince
de los comentarios:
for i in range(5000):
for j in range(3000):
if should_terminate_the_loop:
break
else:
continue # no break encountered
break
La sangría para el bloque else
es correcta. El código usa else
oscuro después de una sintaxis de Python de bucle. Ver ¿Por qué Python usa ''else'' después de los ciclos while y while?
Python le ofrece la posibilidad de hacer algunas de las cosas que puede hacer con un goto utilizando funciones de primera clase. Por ejemplo:
void somefunc(int a)
{
if (a == 1)
goto label1;
if (a == 2)
goto label2;
label1:
...
label2:
...
}
Podría hacerse en Python así:
def func1():
...
def func2():
...
funcmap = {1 : func1, 2 : func2}
def somefunc(a):
funcmap[a]() #Ugly! But it works.
De acuerdo, esa no es la mejor manera de sustituir a goto. Pero sin saber exactamente qué estás tratando de hacer con el goto, es difícil dar un consejo específico.
@ ascobol :
Su mejor opción es incluirlo en una función o usar una excepción. Para la función:
def loopfunc():
while 1:
while 1:
if condition:
return
Para la excepción:
try:
while 1:
while 1:
raise BreakoutException #Not a real exception, invent your own
except BreakoutException:
pass
Usar excepciones para hacer cosas como esta puede ser un poco incómodo si proviene de otro lenguaje de programación. Pero yo diría que si no le gusta usar excepciones, Python no es el idioma para usted. :-)
Quería la misma respuesta y no quería usar goto
. Así que utilicé el siguiente ejemplo (de learnpythonthehardway)
def sample():
print "This room is full of gold how much do you want?"
choice = raw_input("> ")
how_much = int(choice)
if "0" in choice or "1" in choice:
check(how_much)
else:
print "Enter a number with 0 or 1"
sample()
def check(n):
if n < 150:
print "You are not greedy, you win"
exit(0)
else:
print "You are nuts!"
exit(0)
Recientemente escribí un decorador de funciones que habilita goto
en Python, así como así:
from goto import with_goto
@with_goto
def range(start, stop):
i = start
result = []
label .begin
if i == stop:
goto .end
result.append(i)
i += 1
goto .begin
label .end
return result
Aunque no estoy seguro de por qué a uno le gustaría hacer algo así. Dicho eso, no soy muy serio al respecto. Pero me gustaría señalar que este tipo de metaprogramación es posible en Python, al menos en CPython y PyPy, y no solo haciendo un uso incorrecto de la API del depurador como lo hizo ese otro tipo . Sin embargo, debes jugar con el bytecode.
Se ha realizado una versión de trabajo: http://entrian.com/goto/ .
Nota: Fue ofrecida como una broma de April Fool. (trabajando bien)
# Example 1: Breaking out from a deeply nested loop:
from goto import goto, label
for i in range(1, 10):
for j in range(1, 20):
for k in range(1, 30):
print i, j, k
if k == 3:
goto .end
label .end
print "Finished/n"
Excusado es decir que. Sí, es gracioso, pero NO lo uso.
Tengo mi propia manera de hacer gotos. Yo uso scripts de Python separados.
Si quiero hacer un bucle:
file1.py
print("test test")
execfile("file2.py")
a = a + 1
file2.py
print(a)
if a == 10:
execfile("file3.py")
else:
execfile("file1.py")
file3.py
print(a + " equals 10")
( NOTA: esta técnica solo funciona en las versiones de Python 2.x)
puede usar excepciones definidas por el usuario para emular goto
ejemplo:
class goto1(Exception):
pass
class goto2(Exception):
pass
class goto3(Exception):
pass
def loop():
print ''start''
num = input()
try:
if num<=0:
raise goto1
elif num<=2:
raise goto2
elif num<=4:
raise goto3
elif num<=6:
raise goto1
else:
print ''end''
return 0
except goto1 as e:
print ''goto1''
loop()
except goto2 as e:
print ''goto2''
loop()
except goto3 as e:
print ''goto3''
loop()