Y a-t-il un label/goto en Python?
15 réponses
Non, Python ne supporte pas les labels et goto, si c'est ce que vous recherchez. C'est un langage de programmation (hautement) structuré.
Python vous offre la possibilité de faire certaines des choses que vous pourriez faire avec un goto 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 en python comme ceci:
def func1():
...
def func2():
...
funcmap = {1 : func1, 2 : func2}
def somefunc(a):
funcmap[a]() #Ugly! But it works.
Accordée, 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 pari est de l'enfermer 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 des choses comme ça peut sembler un peu embarrassant si vous venez d'un autre langage de programmation. Mais je dirais que si vous n'aimez pas les exceptions, Python n'est pas le langage pour vous. :- )
j'ai récemment , a écrit une fonction décorateur qui permet de 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 voudrait faire quelque chose comme cela. Cela dit, je ne suis pas trop sérieux à son sujet. Mais je tiens à souligner que ce genre de méta-programmation est possible en Python, du moins en CPython et PyPy, et pas seulement en utilisant l'API de déboguage de manière erronée comme l'a fait "l'autre type . Vous avoir à jouer avec le bytecode.
Pour répondre au @ascobol
'à la question à l'aide @bobince
suggestion de la part de vos commentaires:
for i in range(5000):
for j in range(3000):
if should_terminate_the_loop:
break
else:
continue # no break encountered
break
le tiret du bloc else
est correct. Le code utilise l'obscur else
après une syntaxe de Python en boucle. Voir Pourquoi python utilisation 'd'autre' après les boucles for et while?
j'ai trouvé ceci dans le conception officielle de python et L'histoire FAQ .
pourquoi il n'y a pas de goto?
vous pouvez utiliser des exceptions pour fournir un "Goto structuré" qui fonctionne même à travers des appels de fonction. Beaucoup estiment que les exceptions peuvent être imiter toutes les utilisations raisonnables des constructions" go "ou" goto " de C, Fortran, et d'autres langues. 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 sauter au milieu d'une boucle, mais c'est généralement considéré comme un abus de goto de toute façon. À utiliser avec parcimonie.
il est très agréable que cela soit même mentionné dans la FAQ officielle, et qu'un bel échantillon de solution soit fourni. J'aime vraiment python parce que sa communauté traite même goto
comme ceci;)
une version de travail a été réalisée: http://entrian.com/goto / .
Note:il a été offert comme une blague de poisson d'avril. (de travail)
# 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"
inutile de dire. Oui, c'est drôle, mais ne l'utilisez pas.
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 inélégantes) pour imiter break
en Python.
il est techniquement possible d'ajouter une déclaration de type 'goto' à python avec un peu de travail. Nous utiliserons les modules" dis "et" new", tous deux très utiles pour numériser et modifier le code octet python.
l'idée principale derrière la mise en œuvre est de marquer d'abord un bloc de code en utilisant des instructions" goto "et" label". Un décorateur spécial" @goto "sera utilisé pour marquer les fonctions" goto". Ensuite, nous scannons ce code pour ces deux énoncés et appliquons le les modifications nécessaires au code octet sous-jacent. Tout cela se produit au moment de 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 __name__ == '__main__':
@goto
def test1():
print 'Hello'
goto .the_end
print 'world'
label .the_end
print 'the end'
test1()
espérons que cela réponde à la question.
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;
donc mon approche était d'utiliser un booléen pour aider à sortir de la boucle emboîté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
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 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)
j'ai ma propre façon de faire Goto. J'utilise des scripts python séparés.
si je veux boucler:
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 Python 2.X versions)
dans la déclaration Goto de Python est supporté par goto .<label_name>
et label .<label_name>
. Pour plus d'informations s'il vous plaît aller à travers ce lien .
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
généralement sur toute la planète, les gens recommandent d'éviter d'utiliser la déclaration goto. Mais une manipulation de défaillance dans une fonction peut être bien gérée avec seulement la déclaration goto. Même Je ne préfère pas l'utilisation de goto autre que le handler de défaillance.
pour un Goto avant, vous pouvez juste 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 les scénarios simples (c'est-à-dire que l'imbrication de ceux-ci vous mettrait dans une situation confuse)