Existe goto
algum equivalente em Python para poder pular para uma linha específica de código?
goto
em Python quando ele estava traduzindo algum código Fortran para Python. Ele se odiava por isso.
Existe goto
algum equivalente em Python para poder pular para uma linha específica de código?
goto
em Python quando ele estava traduzindo algum código Fortran para Python. Ele se odiava por isso.
Respostas:
Não, o Python não suporta rótulos e vai, se é isso que você procura. É uma linguagem de programação (altamente) estruturada.
O Python oferece a capacidade de fazer algumas das coisas que você poderia fazer com um goto usando funções de primeira classe. Por exemplo:
void somefunc(int a)
{
if (a == 1)
goto label1;
if (a == 2)
goto label2;
label1:
...
label2:
...
}
Pode ser feito em python assim:
def func1():
...
def func2():
...
funcmap = {1 : func1, 2 : func2}
def somefunc(a):
funcmap[a]() #Ugly! But it works.
É verdade que essa não é a melhor maneira de substituir o goto. Mas sem saber exatamente o que você está tentando fazer com o ir, é difícil dar conselhos específicos.
@ ascobol :
Sua melhor aposta é incluí-la em uma função ou usar uma exceção. Para a função:
def loopfunc():
while 1:
while 1:
if condition:
return
Para a exceção:
try:
while 1:
while 1:
raise BreakoutException #Not a real exception, invent your own
except BreakoutException:
pass
Usar exceções para fazer coisas como essa pode parecer um pouco estranho se você vier de outra linguagem de programação. Mas eu argumentaria que, se você não gosta de usar exceções, o Python não é a linguagem para você. :-)
loopfunc
geralmente exigirá contribuições e mais algum esforço para implementar, mas é o melhor caminho na maioria dos casos, eu acho.
Recentemente, escrevi um decorador de funções que habilita goto
no Python, assim:
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
Não sei ao certo por que alguém gostaria de fazer algo assim. Dito isto, eu não sou muito sério sobre isso. Mas eu gostaria de ressaltar que esse tipo de meta programação é realmente possível no Python, pelo menos no CPython e PyPy, e não apenas usando a API do depurador como o outro cara fez. Você precisa mexer com o bytecode.
.begin
e .end
rótulos?
Encontrei isso nas perguntas frequentes oficiais sobre Design e História do python .
Por que não há ir?
Você pode usar exceções para fornecer um "goto estruturado" que funciona mesmo em chamadas de função. Muitos acham que as exceções podem emular convenientemente todos os usos razoáveis das construções "go" ou "goto" de C, Fortran e outros idiomas. Por exemplo:
class label(Exception): pass # declare a label
try:
...
if condition: raise label() # goto label
...
except label: # where to goto
pass
...
Isso não permite que você pule no meio de um loop, mas isso geralmente é considerado um abuso de goto. Use moderadamente.
É muito bom que isso seja mencionado na FAQ oficial e que é fornecida uma amostra de solução legal. Eu realmente gosto de python porque sua comunidade está tratando goto
assim mesmo ;)
goto
é um dos principais foux pas de programação, com certeza, mas a OMI abusa de exceções para emulargoto
é apenas um pouco melhor e ainda deve ser desaprovado. Eu preferiria que os criadores do Python incluíssem goto
na linguagem nas poucas ocasiões em que é realmente útil que não a proibisse porque "é ruim, pessoal" e recomendem o abuso de exceções para obter a mesma funcionalidade (e o mesmo spaghettification de código).
Para responder à @ascobol
pergunta usando @bobince
as sugestões dos comentários:
for i in range(5000):
for j in range(3000):
if should_terminate_the_loop:
break
else:
continue # no break encountered
break
O recuo do else
bloco está correto. O código usa obscuro else
após uma sintaxe Python de loop. Consulte Por que o python usa 'else' após loops for e while?
else
é executado após o loop se break
não tiver sido encontrado. O efeito é que should_terminate_the_loop
termina os loops internos e externos.
return
sugerido por Jason Baker é uma boa alternativa para romper loops profundamente aninhados.
Uma versão de trabalho foi criada: http://entrian.com/goto/ .
Nota: Foi oferecido como uma piada do primeiro de abril. (trabalhando embora)
# 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"
Escusado será dizer que. Sim, é engraçado, mas NÃO o use.
É tecnicamente possível adicionar uma declaração semelhante a 'goto' ao python com algum trabalho. Usaremos os módulos "dis" e "new", ambos muito úteis para varrer e modificar o código de bytes python.
A principal idéia por trás da implementação é marcar primeiro um bloco de código como usando as instruções "goto" e "label". Um decorador especial "@goto" será usado para marcar as funções "goto". Depois, varremos esse código para essas duas instruções e aplicamos as modificações necessárias no código de bytes subjacente. Isso tudo acontece no tempo de compilação do código fonte.
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 isso responda à pergunta.
você pode usar exceções definidas pelo usuário para emulargoto
exemplo:
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()
pip3 install goto-statement
Testado em Python 2.6 a 3.6 e PyPy.
Link: declaração-goto
foo.py
from goto import with_goto
@with_goto
def bar():
label .bar_begin
...
goto .bar_begin
Eu estava procurando por algo parecido com
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;
Portanto, minha abordagem foi usar um booleano para ajudar a sair do loop aninhado para:
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
Existe agora. vamos para
Eu acho que isso pode ser útil para o que você está procurando.
Eu queria a mesma resposta e não queria usar goto
. Então, usei o seguinte exemplo (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)
Eu tenho meu próprio jeito de fazer gotos. Eu uso scripts python separados.
Se eu quiser fazer um loop:
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: Essa técnica funciona apenas nas versões do Python 2.x)
Em vez de um equivalente python goto, uso a instrução break da seguinte maneira para testes rápidos do meu código. Isso pressupõe que você tenha uma base de código estruturada. A variável de teste é inicializada no início de sua função e apenas movo o bloco "If test: break" para o final do bloco ou loop aninhado if-then que desejo testar, modificando a variável de retorno no final do código para refletir a variável de bloco ou loop que estou testando.
def x:
test = True
If y:
# some code
If test:
break
return something
Embora não exista nenhum código equivalente ao goto/label
Python, você ainda pode obter essa funcionalidade degoto/label
usando loops.
Vamos pegar um exemplo de código mostrado abaixo, onde goto/label
pode ser usado em uma linguagem arbitrária que não seja python.
String str1 = 'BACK'
label1:
print('Hello, this program contains goto code\n')
print('Now type BACK if you want the program to go back to the above line of code. Or press the ENTER key if you want the program to continue with further lines of code')
str1 = input()
if str1 == 'BACK'
{
GoTo label1
}
print('Program will continue\nBla bla bla...\nBla bla bla...\nBla bla bla...')
Agora, a mesma funcionalidade do exemplo de código acima pode ser alcançada em python usando um while
loop, como mostrado abaixo.
str1 = 'BACK'
while str1 == 'BACK':
print('Hello, this is a python program containing python equivalent code for goto code\n')
print('Now type BACK if you want the program to go back to the above line of code. Or press the ENTER key if you want the program to continue with further lines of code')
str1 = input()
print('Program will continue\nBla bla bla...\nBla bla bla...\nBla bla bla...')
não, existe uma maneira alternativa de implementar a instrução goto
class id:
def data1(self):
name=[]
age=[]
n=1
while n>0:
print("1. for enter data")
print("2. update list")
print("3. show data")
print("choose what you want to do ?")
ch=int(input("enter your choice"))
if ch==1:
n=int(input("how many elemet you want to enter="))
for i in range(n):
name.append(input("NAME "))
age.append(int(input("age ")))
elif ch==2:
name.append(input("NAME "))
age.append(int(input("age ")))
elif ch==3:
try:
if name==None:
print("empty list")
else:
print("name \t age")
for i in range(n):
print(name[i]," \t ",age[i])
break
except:
print("list is empty")
print("do want to continue y or n")
ch1=input()
if ch1=="y":
n=n+1
else:
print("name \t age")
for i in range(n):
print(name[i]," \t ",age[i])
n=-1
p1=id()
p1.data1()