Y a-t-il un goto
ou tout autre équivalent en Python pour pouvoir sauter à une ligne de code spécifique ?
J'ai corrigé l'indentation de votre autre bloc, ce qui a conduit à un découverte intéressante :
Y a-t-il un goto
ou tout autre équivalent en Python pour pouvoir sauter à une ligne de code spécifique ?
Pour répondre à la @ascobol
La question de la Commission en utilisant @bobince
dans les commentaires :
for i in range(5000):
for j in range(3000):
if should_terminate_the_loop:
break
else:
continue # no break encountered
break
L'indentation pour le else
est correct. Le code utilise l'obscurité else
après une boucle syntaxe Python. Voir Pourquoi python utilise-t-il 'else' après les boucles for et while ?
J'ai corrigé l'indentation de votre autre bloc, ce qui a conduit à un découverte intéressante :
@B1KMusic : l'indentation est correcte telle quelle. Il s'agit d'une syntaxe spéciale de Python. else
est exécuté après la boucle si break
n'a pas été rencontré. L'effet est que should_terminate_the_loop
met fin à les deux les boucles intérieures et extérieures.
J'aurais dû préciser que je n'ai fait cette découverte qu'après avoir fait l'édition. Avant cela, je pensais avoir découvert un bug dans l'interpréteur, j'ai donc fait un tas de cas de test et a fait quelques recherches pour comprendre ce qui se passait. Désolé pour ça.
Il est techniquement possible d'ajouter une instruction de type 'goto' à python avec un peu de travail. Nous utiliserons les modules "dis" et "new", tous deux très utiles pour analyser et modifier le byte code de python.
L'idée principale de l'implémentation est de marquer un bloc de code comme utilisant des instructions "goto" et "label". Un décorateur spécial "@goto" sera utilisé dans le but de marquer les fonctions "goto". Ensuite, nous analysons le code à la recherche de ces deux instructions et appliquons les modifications nécessaires au code octet sous-jacent. Tout cela se passe 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()
J'espère que cela répond à votre question.
Grande fonction utilitaire ! ( goto()
) Cela fonctionne bien pour moi. Mais uniquement dans Python 2. Lorsqu'il est utilisé dans Python 3, il y a de nombreuses exceptions (par exemple new
Le module Py 3 est remplacé par types
, .func_code.
remplacé par .__code__.
etc). Ce serait formidable si vous pouviez adopter cette fonction pour Python 3.
pip3 install goto-statement
Testé sur Python 2.6 à 3.6 et PyPy.
Lien : déclaration de goto
foo.py
from goto import with_goto
@with_goto
def bar():
label .bar_begin
...
goto .bar_begin
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()
Étiquettes pour break
et continue
ont été proposés dans PEP 3136 en 2007, mais elle a été rejetée. Le site Motivation La section de la proposition illustre plusieurs méthodes courantes (bien qu'inélégantes) d'imitation de l'image de marque. break
en Python.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
3 votes
L'étiquette est assez vague. Pouvez-vous être plus précis sur ce que vous recherchez ?
16 votes
import goto
25 votes
Un de mes amis a mis en place
goto
en Python alors qu'il traduisait du code Fortran en Python. Il s'est détesté pour ça.6 votes
github.com/cdjc/goto (c'est beaucoup plus rapide que l'implémentation entrienne)
0 votes
"L'étiquette est plutôt vague", aucune étiquette n'est intelligente, la structure fonctionne comme une machine.
2 votes
Dans le contexte de l'étiquette "goto" est très clair pour tout programmeur expérimenté