Existe-t-il un goto
ou un équivalent dans Python pour pouvoir passer à une ligne de code spécifique?
Non, Python ne prend pas en charge les étiquettes et allez-y, si c'est ce que vous cherchez. C'est un langage de programmation (hautement) structuré.
Python vous offre la possibilité de faire certaines choses avec un goto en utilisant des fonctions de première classe. Par exemple:
void somefunc(int a)
{
if (a == 1)
goto label1;
if (a == 2)
goto label2;
label1:
...
label2:
...
}
Pourrait être fait dans python comme ceci:
def func1():
...
def func2():
...
funcmap = {1 : func1, 2 : func2}
def somefunc(a):
funcmap[a]() #Ugly! But it works.
Certes, ce n'est pas la meilleure façon de remplacer Goto. Mais sans savoir exactement ce que vous essayez de faire avec le goto, il est difficile de donner des conseils spécifiques.
@ ascobol :
Votre meilleur choix est de l'inclure dans une fonction ou d'utiliser une exception. Pour la fonction:
def loopfunc():
while 1:
while 1:
if condition:
return
Pour l'exception:
try:
while 1:
while 1:
raise BreakoutException #Not a real exception, invent your own
except BreakoutException:
pass
Utiliser des exceptions pour faire de telles choses peut sembler un peu gênant si vous venez d'un autre langage de programmation. Mais je dirais que si vous n'aimez pas utiliser les exceptions, Python n'est pas la langue pour vous. :-)
J'ai récemment écrit un décorateur de fonctions qui active goto
en Python, juste comme ça:
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
Je ne sais pas pourquoi on aimerait faire quelque chose comme ça. Cela dit, je ne suis pas trop sérieux à ce sujet. Mais je tiens à souligner que ce type de méta-programmation est réellement possible en Python, du moins dans CPython et PyPy, et pas seulement en utilisant à mauvais escient l’API du débogueur comme cela autre type l’a fait. Cependant, vous devez jouer avec le bytecode.
J'ai trouvé cela dans la FAQ officielle python Conception et historique .
Pourquoi n'y a-t-il pas de goto?
Vous pouvez utiliser des exceptions pour fournir un "goto structuré" qui fonctionne même pour les appels de fonction. Beaucoup pensent que les exceptions peuvent facilement imiter toutes les utilisations raisonnables des constructions "aller" ou "aller" des langages C, Fortran et autres. Par exemple:
class label(Exception): pass # declare a label
try:
...
if condition: raise label() # goto label
...
except label: # where to goto
pass
...
Cela ne vous permet pas de vous placer au milieu d’une boucle, mais c’est généralement considéré comme un abus de goto. Utiliser avec parcimonie.
C'est très gentil que cela soit même mentionné dans la FAQ officielle et qu'un exemple de solution Nice soit fourni. J'aime beaucoup python parce que sa communauté traite même goto
comme ceci;)
Pour répondre à la question question de @ascobol
en utilisant la suggestion de @bobince
à partir des commentaires:
for i in range(5000):
for j in range(3000):
if should_terminate_the_loop:
break
else:
continue # no break encountered
break
Le retrait du bloc else
est correct. Le code utilise obscure else
après une syntaxe de boucle Python. Voir Pourquoi python utilise-t-il 'else' après les boucles for et while?
Une version de travail a été faite: http://entrian.com/goto/ .
Remarque: il s'agissait d'une blague du poisson d'avril. (travaille 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"
Il va sans dire. Oui c'est drôle, mais ne l'utilisez pas.
Il est techniquement possible d’ajouter une tâche similaire à python. Nous allons utiliser les modules "dis" et "new", tous deux très utiles pour scanner et modifier le code python.
L'idée principale derrière l'implémentation est de commencer par marquer un bloc de code en utilisant les instructions "goto" et "label". Un décorateur spécial "@goto" sera utilisé pour marquer les fonctions "goto". Ensuite, nous analysons ce code pour ces deux instructions et appliquons les modifications nécessaires au code d'octet sous-jacent. Tout cela se passe à la compilation du code source.
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 __== '__main__':
@goto
def test1():
print 'Hello'
goto .the_end
print 'world'
label .the_end
print 'the end'
test1()
J'espère que cela répond à la question.
Des étiquettes pour break
et continue
ont été proposées dans PEP 3136 en 2007, mais elles ont été rejetées. La section Motivation de la proposition illustre plusieurs méthodes courantes (si elles sont inélégantes) pour imiter le libellé break
en Python.
vous pouvez utiliser Exceptions définies par l'utilisateur pour émuler goto
exemple:
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()
Je cherchais quelque chose de similaire à
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;
Mon approche consistait donc à utiliser un booléen pour aider à sortir de la boucle imbriquée:
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
Il y a maintenant. goto
Je pense que cela pourrait être utile pour ce que vous recherchez.
J'ai ma propre façon de faire des gotos. J'utilise des scripts python distincts.
Si je veux faire une boucle:
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")
(NOTE: Cette technique ne fonctionne que sur les versions Python 2.x)
Je voulais la même réponse et je ne voulais pas utiliser goto
. J'ai donc utilisé l'exemple suivant (tiré 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)
Pour un Goto en avant, vous pouvez simplement ajouter:
while True:
if some condition:
break
#... extra code
break # force code to exit. Needed at end of while loop
#... continues here
Cela n’aide que pour des scénarios simples (c’est-à-dire qu’ils seraient imbriqués).
pip3 install goto-statement
Testé sur Python 2.6 à 3.6 et PyPy.
Lien: goto-statement
foo.py
from goto import with_goto
@with_goto
def bar(start, stop):
label .bar_begin
...
goto .bar_begin
Au lieu d'un équivalent python, j'utilise l'instruction break de la manière suivante pour effectuer des tests rapides de mon code. Cela suppose que vous ayez une base de code structurée. La variable de test est initialisée au début de votre fonction et je déplace juste le bloc "If test: break" à la fin du bloc imbriqué if-then ou de la boucle que je veux tester, en modifiant la variable de retour à la fin du code pour refléter la variable de bloc ou de boucle que je teste.
def x:
test = True
If y:
# some code
If test:
break
return something
non, il existe un autre moyen d'implémenter l'instruction 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()