Python vous offre la possibilité de faire certaines des choses que vous pourriez faire avec un goto en utilisant des fonctions de première classe. Par exemple:
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 précis.
Votre meilleur pari est de l'enfermer dans une fonction ou d'utiliser une exception. Pour la fonction:
def loopfunc():while1:while1:if condition:return
Pour l'exception:
try:while1:while1:raiseBreakoutException#Not a real exception, invent your ownexceptBreakoutException:pass
Utiliser des exceptions pour faire des choses comme celle-ci 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 le langage qu'il vous faut. :-)
Utilisez-le judicieusement. Les exceptions en Python sont plus rapides que la plupart des autres langages. Mais ils sont encore lents si vous devenez fou avec eux.
Jason Baker
Juste un avis: loopfuncnécessitera généralement des contributions et un peu plus d'efforts à mettre en œuvre, mais c'est le meilleur moyen dans la plupart des cas, je pense.
from goto import with_goto@with_gotodef range(start, stop):
i = start
result =[]
label .beginif i == stop:
goto .end
result.append(i)
i +=1
goto .begin
label .endreturn 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 j'aimerais souligner que ce type de métaprogrammation est réellement possible en Python, au moins en CPython et PyPy, et pas seulement en abusant de l'API du débogueur comme l'a fait cet autre gars . Vous devez cependant jouer avec le bytecode.
Vous pouvez utiliser des exceptions pour fournir un «goto structuré» qui fonctionne même entre les appels de fonction. Beaucoup pensent que les exceptions peuvent facilement émuler toutes les utilisations raisonnables des constructions «go» ou «goto» de C, Fortran et d'autres langages. Par exemple:
class label(Exception):pass# declare a labeltry:...if condition:raise label()# goto label...except label:# where to gotopass...
Cela ne vous permet pas de 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.
C'est très bien que cela soit même mentionné dans la FAQ officielle et qu'un bel exemple de solution soit fourni. J'aime vraiment python parce que sa communauté traite même gotocomme ça;)
Abuser gotoest un problème majeur de programmation, bien sûr, mais l'OMI abuser des exceptions pour émuler goton'est que légèrement mieux et devrait encore être fortement désapprouvé. J'aurais préféré que les créateurs de Python incluent gotodans le langage pour les rares occasions où cela est réellement utile que de l'interdire parce que "c'est mauvais, les gars" et puis recommander d'abuser des exceptions pour obtenir la même fonctionnalité (et la même spaghettification du code).
Abion47 le
15
Pour répondre à la @ascobolquestion de en utilisant @bobincela suggestion de dans les commentaires:
for i in range(5000):for j in range(3000):if should_terminate_the_loop:breakelse:continue# no break encounteredbreak
@ B1KMusic: le retrait est correct tel quel. C'est une syntaxe Python spéciale. elseest exécuté après la boucle s'il breakn'a pas été rencontré. L'effet est que should_terminate_the_looptermine les boucles internes et externes.
jfs
1
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 bogue dans l'interpréteur, alors j'ai fait un tas de cas de test et fait des recherches pour comprendre ce qui se passait. Désolé pour ça.
Braden Best
1
Maintenant que je comprends ce qui se passe, je suis d'accord, c'est un code ésotérique qui serait fait beaucoup plus facilement avec des méthodes plus traditionnelles
Braden Best
1
@ B1KMusic: Non. Dupliquer du code pour contourner votre ignorance n'est pas une bonne solution. Oui. returnsuggéré par @Jason Baker est une bonne alternative pour sortir de boucles profondément imbriquées.
Remarque: il s'agissait d'une blague du poisson d'avril. (fonctionne bien)
# Example 1: Breaking out from a deeply nested loop:from goto import goto, labelfor i in range(1,10):for j in range(1,20):for k in range(1,30):print i, j, kif k ==3:
goto .end
label .endprint"Finished\n"
Il va sans dire. Oui c'est drôle, mais ne l'utilisez pas.
me semble mieux que d'utiliser 3 pauses ... bien sûr, il y a d'autres façons de l'écrire aussi.
Nick
1
@Nick L'utilisation de la fonction avec retour est encore bien meilleure.
Erik Šťastný
7
Des étiquettes pour breaket continueont é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 étiquetées breaken Python.
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 scanner et modifier le code octet python.
L'idée principale derrière l'implémentation est de marquer d'abord un bloc de code comme utilisant des 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 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 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;
Mon approche a donc été d'utiliser un booléen pour aider à sortir des boucles for imbriquées:
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
Je voulais la même réponse et je ne voulais pas l'utiliser goto. J'ai donc utilisé l'exemple suivant (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)
Au lieu d'un équivalent python goto, j'utilise l'instruction break de la manière suivante pour des tests rapides de mon code. Cela suppose que vous disposez d'une base de code structurée. La variable de test est initialisée au début de votre fonction et je déplace simplement le bloc "If test: break" à la fin du bloc ou de la boucle imbriquée if-then 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 =TrueIf y:# some codeIf test:breakreturn something
Bien qu'il n'y ait pas de code équivalent à goto/labelPython, vous pouvez toujours obtenir une telle fonctionnalité en goto/labelutilisant des boucles.
Prenons un exemple de code ci-dessous où goto/labelpeut être utilisé dans un langage arbitraire autre que 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...')
Maintenant, la même fonctionnalité de l'exemple de code ci-dessus peut être obtenue en python en utilisant une whileboucle comme indiqué ci-dessous.
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...')
non il existe une autre façon d'implémenter l'instruction 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
en Python quand il traduisait du code Fortran en Python. Il se détestait pour ça.Réponses:
Non, Python ne prend pas en charge les étiquettes et goto, si c'est ce que vous recherchez. C'est un langage de programmation (hautement) structuré.
la source
Python vous offre la possibilité de faire certaines des choses que vous pourriez faire avec un goto en utilisant des fonctions de première classe. Par exemple:
Cela pourrait être fait en python comme ceci:
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 précis.
@ ascobol :
Votre meilleur pari est de l'enfermer dans une fonction ou d'utiliser une exception. Pour la fonction:
Pour l'exception:
Utiliser des exceptions pour faire des choses comme celle-ci 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 le langage qu'il vous faut. :-)
la source
loopfunc
nécessitera généralement des contributions et un peu plus d'efforts à mettre en œuvre, mais c'est le meilleur moyen dans la plupart des cas, je pense.J'ai récemment écrit un décorateur de fonctions qui permet
goto
en Python, comme ça:Je ne sais pas pourquoi on aimerait faire quelque chose comme ça. Cela dit, je ne suis pas trop sérieux à ce sujet. Mais j'aimerais souligner que ce type de métaprogrammation est réellement possible en Python, au moins en CPython et PyPy, et pas seulement en abusant de l'API du débogueur comme l'a fait cet autre gars . Vous devez cependant jouer avec le bytecode.
la source
.begin
et les.end
étiquettes?J'ai trouvé cela dans la FAQ officielle sur la conception et l'histoire de python .
C'est très bien que cela soit même mentionné dans la FAQ officielle et qu'un bel exemple de solution soit fourni. J'aime vraiment python parce que sa communauté traite même
goto
comme ça;)la source
goto
est un problème majeur de programmation, bien sûr, mais l'OMI abuser des exceptions pour émulergoto
n'est que légèrement mieux et devrait encore être fortement désapprouvé. J'aurais préféré que les créateurs de Python incluentgoto
dans le langage pour les rares occasions où cela est réellement utile que de l'interdire parce que "c'est mauvais, les gars" et puis recommander d'abuser des exceptions pour obtenir la même fonctionnalité (et la même spaghettification du code).Pour répondre à la
@ascobol
question de en utilisant@bobince
la suggestion de dans les commentaires:Le retrait du
else
bloc est correct. Le code utilise obscureelse
après une syntaxe Python en boucle. Voir Pourquoi python utilise-t-il 'else' après les boucles for et while?la source
else
est exécuté après la boucle s'ilbreak
n'a pas été rencontré. L'effet est queshould_terminate_the_loop
termine les boucles internes et externes.return
suggéré par @Jason Baker est une bonne alternative pour sortir de boucles profondément imbriquées.Une version fonctionnelle a été créée: http://entrian.com/goto/ .
Remarque: il s'agissait d'une blague du poisson d'avril. (fonctionne bien)
Il va sans dire. Oui c'est drôle, mais ne l'utilisez pas.
la source
Des étiquettes pour
break
etcontinue
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 étiquetéesbreak
en Python.la source
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 scanner et modifier le code octet python.
L'idée principale derrière l'implémentation est de marquer d'abord un bloc de code comme utilisant des 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 produit au moment de la compilation du code source.
J'espère que cela répond à la question.
la source
vous pouvez utiliser des exceptions définies par l'utilisateur pour émuler
goto
exemple:
la source
Python 2 et 3
Lien: goto-statement
foo.py
la source
Je cherchais quelque chose de similaire à
Mon approche a donc été d'utiliser un booléen pour aider à sortir des boucles for imbriquées:
la source
Il y a maintenant. aller à
Je pense que cela pourrait être utile pour ce que vous recherchez.
la source
Je voulais la même réponse et je ne voulais pas l'utiliser
goto
. J'ai donc utilisé l'exemple suivant (de learnpythonthehardway)la source
J'ai ma propre façon de faire des gotos. J'utilise des scripts python séparés.
Si je veux faire une boucle:
file1.py
file2.py
file3.py
( REMARQUE: cette technique ne fonctionne que sur les versions Python 2.x)
la source
Pour un aller en avant, vous pouvez simplement ajouter:
Cela n'aide cependant que pour des scénarios simples (c'est-à-dire que leur imbrication vous mettrait dans le désordre)
la source
Au lieu d'un équivalent python goto, j'utilise l'instruction break de la manière suivante pour des tests rapides de mon code. Cela suppose que vous disposez d'une base de code structurée. La variable de test est initialisée au début de votre fonction et je déplace simplement le bloc "If test: break" à la fin du bloc ou de la boucle imbriquée if-then 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.
la source
Bien qu'il n'y ait pas de code équivalent à
goto/label
Python, vous pouvez toujours obtenir une telle fonctionnalité engoto/label
utilisant des boucles.Prenons un exemple de code ci-dessous où
goto/label
peut être utilisé dans un langage arbitraire autre que python.Maintenant, la même fonctionnalité de l'exemple de code ci-dessus peut être obtenue en python en utilisant une
while
boucle comme indiqué ci-dessous.la source
non il existe une autre façon d'implémenter l'instruction goto
la source