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.
Sua melhor aposta é incluí-la em uma função ou usar uma exceção. Para a função:
def loopfunc():while1:while1:if condition:return
Para a exceção:
try:while1:while1:raiseBreakoutException#Not a real exception, invent your ownexceptBreakoutException: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ê. :-)
Use-o criteriosamente. Exceções no Python são mais rápidas que a maioria das outras linguagens. Mas eles ainda são lentos se você enlouquecer com eles.
Jason Baker
Apenas um aviso: loopfuncgeralmente exigirá contribuições e mais algum esforço para implementar, mas é o melhor caminho na maioria dos casos, eu acho.
from goto import with_goto
@with_gotodef 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.
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 labeltry:...if condition:raise label()# goto label...except label:# where to gotopass...
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 gotoassim mesmo ;)
O abuso 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 gotona 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).
Abion47 9/07
15
Para responder à @ascobolpergunta usando @bobinceas sugestões dos comentários:
for i in range(5000):for j in range(3000):if should_terminate_the_loop:breakelse:continue# no break encounteredbreak
@ B1KMusic: o recuo está correto como está. É uma sintaxe especial do Python. elseé executado após o loop se breaknão tiver sido encontrado. O efeito é que should_terminate_the_looptermina os loops internos e externos.
jfs
1
Eu deveria ter especificado que só fiz essa descoberta depois de fazer a edição. Antes disso, pensei que havia descoberto um bug no intérprete, então fiz vários casos de teste e fiz algumas pesquisas para entender o que estava acontecendo. Me desculpe por isso.
Braden Best
1
Agora que eu entendo o que está acontecendo, eu concordo, que é um código de esotérico que seria feito muito mais facilmente com métodos mais tradicionais
Braden Melhor
1
@ B1KMusic: Não. Duplicar código para solucionar sua ignorância não é uma boa solução. Sim. returnsugerido por Jason Baker é uma boa alternativa para romper loops profundamente aninhados.
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.
parece melhor para mim do que usar três pausas ... é claro que existem outras maneiras de escrevê-lo também.
Nick
1
@ Nick O uso da função com retorno parece ainda melhor.
Erik Šťastný
7
Os rótulos para breake continueforam propostos no PEP 3136 em 2007, mas foram rejeitados. A seção Motivação da proposta ilustra vários métodos comuns (se deselegantes) para imitar rotulados breakem Python.
É 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 gotoswhile 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 +=2continueif 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 jumpsfor label,index in gotos.items():if label notin labels:raiseException("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__':@gotodef test1():print'Hello'
goto .the_end
print'world'
label .the_end
print'the end'
test1()
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 stuffif(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 =Falsefor b in xrange(1,5):if(get_out):breakfor c in xrange(1,5):if(get_out):breakfor d in xrange(1,5):# do some stuffif(condition(e)):
get_out =Truebreak
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)
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 =TrueIf y:# some codeIf test:breakreturn something
Embora não exista nenhum código equivalente ao goto/labelPython, você ainda pode obter essa funcionalidade degoto/label usando loops.
Vamos pegar um exemplo de código mostrado abaixo, onde goto/labelpode 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 whileloop, 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=1while 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])breakexcept:print("list is empty")print("do want to continue y or n")
ch1=input()if ch1=="y":
n=n+1else:print("name \t age")for i in range(n):print(name[i]," \t ",age[i])
n=-1
p1=id()
p1.data1()
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.
fonte
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:
Pode ser feito em python assim:
É 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:
Para a exceção:
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ê. :-)
fonte
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: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.
fonte
.begin
e.end
rótulos?Encontrei isso nas perguntas frequentes oficiais sobre Design e História do python .
É 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 ;)fonte
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íssemgoto
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:O recuo do
else
bloco está correto. O código usa obscuroelse
após uma sintaxe Python de loop. Consulte Por que o python usa 'else' após loops for e while?fonte
else
é executado após o loop sebreak
não tiver sido encontrado. O efeito é queshould_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)
Escusado será dizer que. Sim, é engraçado, mas NÃO o use.
fonte
Os rótulos para
break
econtinue
foram propostos no PEP 3136 em 2007, mas foram rejeitados. A seção Motivação da proposta ilustra vários métodos comuns (se deselegantes) para imitar rotuladosbreak
em Python.fonte
É 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.
Espero que isso responda à pergunta.
fonte
você pode usar exceções definidas pelo usuário para emular
goto
exemplo:
fonte
Python 2 e 3
Link: declaração-goto
foo.py
fonte
Eu estava procurando por algo parecido com
Portanto, minha abordagem foi usar um booleano para ajudar a sair do loop aninhado para:
fonte
Existe agora. vamos para
Eu acho que isso pode ser útil para o que você está procurando.
fonte
Eu queria a mesma resposta e não queria usar
goto
. Então, usei o seguinte exemplo (de learnpythonthehardway)fonte
Eu tenho meu próprio jeito de fazer gotos. Eu uso scripts python separados.
Se eu quiser fazer um loop:
file1.py
file2.py
file3.py
( NOTA: Essa técnica funciona apenas nas versões do Python 2.x)
fonte
Para avançar, você pode adicionar:
Porém, isso só ajuda em cenários simples (ou seja, aninhar esses itens causaria uma confusão)
fonte
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.
fonte
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.Agora, a mesma funcionalidade do exemplo de código acima pode ser alcançada em python usando um
while
loop, como mostrado abaixo.fonte
não, existe uma maneira alternativa de implementar a instrução goto
fonte