Gibt es goto
in Python ein oder ein gleichwertiges Element, um zu einer bestimmten Codezeile springen zu können?
goto
in Python implementiert, als er Fortran-Code in Python übersetzte. Er hasste sich dafür.
Gibt es goto
in Python ein oder ein gleichwertiges Element, um zu einer bestimmten Codezeile springen zu können?
goto
in Python implementiert, als er Fortran-Code in Python übersetzte. Er hasste sich dafür.
Antworten:
Nein, Python unterstützt keine Labels und goto, wenn Sie danach suchen. Es ist eine (stark) strukturierte Programmiersprache.
Python bietet Ihnen die Möglichkeit, einige der Dinge zu tun, die Sie mit einem goto mit erstklassigen Funktionen tun können. Beispielsweise:
void somefunc(int a)
{
if (a == 1)
goto label1;
if (a == 2)
goto label2;
label1:
...
label2:
...
}
Könnte in Python so gemacht werden:
def func1():
...
def func2():
...
funcmap = {1 : func1, 2 : func2}
def somefunc(a):
funcmap[a]() #Ugly! But it works.
Zugegeben, das ist nicht der beste Weg, um goto zu ersetzen. Aber ohne genau zu wissen, was Sie mit dem goto machen wollen, ist es schwierig, spezifische Ratschläge zu geben.
@ ascobol :
Am besten schließen Sie es entweder in eine Funktion ein oder verwenden eine Ausnahme. Für die Funktion:
def loopfunc():
while 1:
while 1:
if condition:
return
Für die Ausnahme:
try:
while 1:
while 1:
raise BreakoutException #Not a real exception, invent your own
except BreakoutException:
pass
Die Verwendung von Ausnahmen für solche Aufgaben kann sich etwas unangenehm anfühlen, wenn Sie aus einer anderen Programmiersprache stammen. Aber ich würde argumentieren, dass Python nicht die Sprache für Sie ist, wenn Sie keine Ausnahmen verwenden möchten. :-)
loopfunc
Implementierung erfordert im Allgemeinen Eingaben und etwas mehr Aufwand, ist aber in den meisten Fällen meiner Meinung nach der beste Weg.
Ich habe kürzlich einen Funktionsdekorator geschrieben , der goto
in Python einfach Folgendes ermöglicht :
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
Ich bin mir nicht sicher, warum man so etwas machen möchte. Das heißt, ich meine es nicht zu ernst. Aber ich möchte darauf hinweisen, dass diese Art der Metaprogrammierung in Python tatsächlich möglich ist, zumindest in CPython und PyPy, und nicht nur durch den Missbrauch der Debugger-API wie dieser andere Typ . Sie müssen sich jedoch mit dem Bytecode herumschlagen.
.begin
und .end
beschriftet dies nur ?
Ich fand dies in den offiziellen Python Design and History FAQ .
Warum gibt es kein goto?
Sie können Ausnahmen verwenden, um ein „strukturiertes Goto“ bereitzustellen, das sogar über Funktionsaufrufe hinweg funktioniert. Viele sind der Meinung, dass Ausnahmen alle vernünftigen Verwendungen der Konstrukte "go" oder "goto" von C, Fortran und anderen Sprachen bequem emulieren können. Beispielsweise:
class label(Exception): pass # declare a label
try:
...
if condition: raise label() # goto label
...
except label: # where to goto
pass
...
Dies erlaubt Ihnen nicht, in die Mitte einer Schleife zu springen, aber das wird normalerweise sowieso als Missbrauch von goto angesehen. Sparsam verwenden.
Es ist sehr schön, dass dies sogar in den offiziellen FAQ erwähnt wird und dass ein schönes Lösungsbeispiel bereitgestellt wird. Ich mag Python wirklich, weil seine Community sogar goto
so behandelt ;)
So beantworten Sie die @ascobol
Frage mit @bobince
dem Vorschlag aus den Kommentaren:
for i in range(5000):
for j in range(3000):
if should_terminate_the_loop:
break
else:
continue # no break encountered
break
Der Einzug für den else
Block ist korrekt. Der Code verwendet obskur else
nach einer Python-Schleifensyntax. Siehe Warum verwendet Python 'else' nach for- und while-Schleifen?
else
wird nach der Schleife ausgeführt, wenn break
sie nicht gefunden wurde. Der Effekt ist , dass should_terminate_the_loop
endet beide inneren und äußeren Schleifen.
return
vorgeschlagen von @Jason Baker ist eine gute Alternative, um aus tief verschachtelten Schleifen auszubrechen.
Eine funktionierende Version wurde erstellt: http://entrian.com/goto/ .
Hinweis: Es wurde als Aprilscherz angeboten. (arbeitet aber)
# 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"
Unnötig zu erwähnen. Ja, es ist lustig, aber benutze es NICHT.
Etiketten für break
und continue
wurden bereits 2007 in PEP 3136 vorgeschlagen , aber abgelehnt. Der Abschnitt Motivation des Vorschlags zeigt einige gängige (wenn auch unelegante) Methoden zur Nachahmung von break
in Python beschrifteten .
Es ist technisch machbar, Python mit etwas Arbeit eine 'goto'-ähnliche Anweisung hinzuzufügen. Wir werden die Module "dis" und "new" verwenden, die beide sehr nützlich sind, um Python-Byte-Code zu scannen und zu ändern.
Die Hauptidee hinter der Implementierung besteht darin, zunächst einen Codeblock mit den Anweisungen "goto" und "label" zu markieren. Ein spezieller "@goto" -Dekorator wird zum Markieren von "goto" -Funktionen verwendet. Anschließend scannen wir diesen Code nach diesen beiden Anweisungen und wenden die erforderlichen Änderungen auf den zugrunde liegenden Bytecode an. Dies alles geschieht zum Zeitpunkt der Kompilierung des Quellcodes.
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()
Hoffe das beantwortet die Frage.
Sie können benutzerdefinierte Ausnahmen zum Emulieren verwendengoto
Beispiel:
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()
pip3 install goto-statement
Getestet auf Python 2.6 bis 3.6 und PyPy.
Link: goto-Anweisung
foo.py.
from goto import with_goto
@with_goto
def bar():
label .bar_begin
...
goto .bar_begin
Ich suchte nach etwas Ähnlichem
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;
Mein Ansatz war es also, einen Booleschen Wert zu verwenden, um aus den verschachtelten for-Schleifen auszubrechen:
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
Ich wollte die gleiche Antwort und wollte sie nicht verwenden goto
. Also habe ich das folgende Beispiel verwendet (von 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)
Ich habe meine eigene Art, Gotos zu machen. Ich benutze separate Python-Skripte.
Wenn ich eine Schleife machen möchte:
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")
( HINWEIS: Diese Technik funktioniert nur in Python 2.x-Versionen.)
Für ein Forward Goto können Sie einfach hinzufügen:
while True:
if some condition:
break
#... extra code
break # force code to exit. Needed at end of while loop
#... continues here
Dies hilft jedoch nur bei einfachen Szenarien (dh wenn Sie diese verschachteln, geraten Sie in Unordnung).
Anstelle eines Python-Goto-Äquivalents verwende ich die break-Anweisung folgendermaßen, um meinen Code schnell zu testen. Dies setzt voraus, dass Sie eine strukturierte Codebasis haben. Die Testvariable wird zu Beginn Ihrer Funktion initialisiert und ich verschiebe einfach den Block "If test: break" an das Ende des verschachtelten if-then-Blocks oder der verschachtelten Schleife, die ich testen möchte, und ändere die Rückgabevariable am Ende des Codes um die Block- oder Schleifenvariable wiederzugeben, die ich teste.
def x:
test = True
If y:
# some code
If test:
break
return something
Obwohl es keinen Code gibt, der goto/label
Python entspricht, könnten Sie dennoch solche Funktionen für die goto/label
Verwendung von Schleifen erhalten.
Nehmen goto/label
wir ein unten gezeigtes Codebeispiel , das in einer anderen Sprache als Python verwendet werden kann.
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...')
Jetzt kann die gleiche Funktionalität des obigen Codebeispiels in Python mithilfe einer while
Schleife wie unten gezeigt erreicht werden.
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...')
Nein, es gibt eine alternative Möglichkeit, die goto-Anweisung zu implementieren
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()