def func1():...def func2():...
funcmap ={1: func1,2: func2}def somefunc(a):
funcmap[a]()#Ugly! But it works.
To prawda, że nie jest to najlepszy sposób na zastąpienie goto. Ale nie wiedząc dokładnie, co próbujesz zrobić z goto, trudno jest udzielić konkretnej porady.
Najlepszym rozwiązaniem jest umieszczenie go w funkcji lub użycie wyjątku. Dla funkcji:
def loopfunc():while1:while1:if condition:return
Z wyjątkiem:
try:while1:while1:raiseBreakoutException#Not a real exception, invent your ownexceptBreakoutException:pass
Używanie wyjątków do robienia takich rzeczy może wydawać się nieco niezręczne, jeśli pochodzisz z innego języka programowania. Ale argumentowałbym, że jeśli nie lubisz używać wyjątków, Python nie jest dla ciebie językiem. :-)
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
Nie jestem jednak pewien, dlaczego chciałoby się coś takiego zrobić. To powiedziawszy, nie podchodzę do tego poważnie. Chciałbym jednak zwrócić uwagę, że tego rodzaju metaprogramowanie jest w rzeczywistości możliwe w Pythonie, przynajmniej w CPython i PyPy, i nie tylko przez niewłaściwe użycie interfejsu API debuggera, tak jak zrobił to tamten facet . Musisz jednak zadzierać z kodem bajtowym.
Możesz użyć wyjątków, aby zapewnić „strukturalne goto”, które działa nawet w przypadku wywołań funkcji. Wielu uważa, że wyjątki mogą wygodnie naśladować wszystkie rozsądne zastosowania konstrukcji „go” lub „goto” w językach C, Fortran i innych. Na przykład:
class label(Exception):pass# declare a labeltry:...if condition:raise label()# goto label...except label:# where to gotopass...
Nie pozwala to wskoczyć w środek pętli, ale i tak jest to zwykle uważane za nadużycie goto. Używaj oszczędnie.
To bardzo miłe, że jest to nawet wspomniane w oficjalnym FAQ i że dostarczono fajną próbkę rozwiązania. Bardzo lubię Pythona, ponieważ jego społeczność traktuje nawet w gototen sposób;)
Z gotopewnością nadużywanie jest poważnym foux pasem programistycznym, ale nadużywanie wyjątków przez IMO w celu emulacji gotojest tylko nieznacznie lepsze i nadal powinno być mocno krytykowane. Wolałbym, żeby twórcy Pythona włączyli gotodo języka kilka sytuacji, w których faktycznie jest to użyteczne, niż zablokować go, ponieważ „to jest złe, chłopaki”, a następnie zalecić nadużywanie wyjątków, aby uzyskać tę samą funkcjonalność (i ten sam kod spaghetti).
Poprawiłem wcięcie w innym bloku, co doprowadziło do ciekawego odkrycia :
Braden Best,
3
@ B1KMusic: wcięcie jest poprawne bez zmian. Jest to specjalna składnia Pythona. elsejest wykonywany po pętli, jeśli breaknie został napotkany. Efektem jest to, że should_terminate_the_loopzamyka obie pętle wewnętrzne i zewnętrzne.
jfs
1
Powinienem był sprecyzować, że dokonałem tego odkrycia dopiero po dokonaniu edycji. Wcześniej wydawało mi się, że znalazłem błąd w tłumaczu, więc stworzyłem kilka przypadków testowych i przeprowadziłem badania, aby zrozumieć, co się dzieje. Przepraszam za to.
Braden Best
1
Teraz, gdy rozumiem, co się dzieje, zgadzam się, że jest to jakiś ezoteryczny kod, który można by zrobić o wiele łatwiej przy użyciu bardziej tradycyjnych metod
Braden Best,
1
@ B1KMusic: Nie. Powielanie kodu w celu obejścia ignorancji nie jest dobrym rozwiązaniem. Tak. returnsugerowane przez @Jason Baker to dobra alternatywa dla wyrwania się z głęboko zagnieżdżonych pętli.
Uwaga: był oferowany jako żart primaaprilisowy. (choć działa)
# 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"
Nie trzeba dodawać że. Tak, to zabawne, ale NIE używaj go.
wygląda dla mnie lepiej niż 3 przerwy ... oczywiście są też inne sposoby, aby to zapisać.
Nick
1
@Nick Użycie funkcji z powrotem wygląda jeszcze lepiej.
Erik Šťastný
7
Etykiety breaki continuezostały zaproponowane w PEP 3136 w 2007 roku, ale zostały odrzucone. Sekcja Motywacja propozycji ilustruje kilka powszechnych (jeśli nieeleganckich) metod naśladowania oznaczonych breakw Pythonie.
Jest technicznie wykonalne, aby dodać do Pythona instrukcję podobną do „goto”. Będziemy używać modułów „dis” i „new”, które są bardzo przydatne do skanowania i modyfikowania kodu bajtowego Pythona.
Główną ideą implementacji jest najpierw oznaczenie bloku kodu za pomocą instrukcji „goto” i „label”. Specjalny dekorator „@goto” będzie używany do oznaczania funkcji „goto”. Następnie skanujemy ten kod w poszukiwaniu tych dwóch instrukcji i wprowadzamy niezbędne modyfikacje do bazowego kodu bajtowego. To wszystko dzieje się w czasie kompilacji kodu źródłowego.
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;
Więc moje podejście polegało na użyciu wartości logicznej, aby pomóc wyrwać się z zagnieżdżonych pętli for:
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
Chciałem tej samej odpowiedzi i nie chciałem używać goto. Więc użyłem następującego przykładu (z 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)
Zamiast odpowiednika goto w Pythonie używam instrukcji break w następujący sposób do szybkich testów mojego kodu. Zakłada się, że masz strukturalną podstawę kodu. Zmienna testowa jest inicjowana na początku twojej funkcji i po prostu przenoszę blok "If test: break" na koniec zagnieżdżonego bloku lub pętli if-then, które chcę przetestować, modyfikując zmienną zwracaną na końcu kodu aby odzwierciedlić testowaną zmienną bloku lub pętli.
def x:
test =TrueIf y:# some codeIf test:breakreturn something
Chociaż nie ma żadnego kodu odpowiadającego temu goto/labelw Pythonie, nadal możesz uzyskać taką funkcjonalnośćgoto/label przy użyciu pętli.
Weźmy przykładowy kod pokazany poniżej, w którym goto/labelmożna go użyć w dowolnym języku innym niż 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...')
Teraz tę samą funkcjonalność powyższego przykładu kodu można osiągnąć w Pythonie za pomocą whilepętli, jak pokazano poniżej.
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...')
nie, istnieje alternatywny sposób implementacji instrukcji 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
w Pythonie, kiedy tłumaczył kod w języku Fortran na Python. Nienawidził siebie za to.Odpowiedzi:
Nie, Python nie obsługuje etykiet i gotowe, jeśli o to ci chodzi. Jest to (wysoce) ustrukturyzowany język programowania.
źródło
Python oferuje możliwość zrobienia niektórych rzeczy, które można zrobić za pomocą goto, używając funkcji pierwszej klasy. Na przykład:
Można to zrobić w Pythonie w ten sposób:
To prawda, że nie jest to najlepszy sposób na zastąpienie goto. Ale nie wiedząc dokładnie, co próbujesz zrobić z goto, trudno jest udzielić konkretnej porady.
@ ascobol :
Najlepszym rozwiązaniem jest umieszczenie go w funkcji lub użycie wyjątku. Dla funkcji:
Z wyjątkiem:
Używanie wyjątków do robienia takich rzeczy może wydawać się nieco niezręczne, jeśli pochodzisz z innego języka programowania. Ale argumentowałbym, że jeśli nie lubisz używać wyjątków, Python nie jest dla ciebie językiem. :-)
źródło
loopfunc
generalnie będzie wymagał wkładu i trochę więcej wysiłku, aby go wdrożyć, ale w większości przypadków jest to najlepszy sposób.Niedawno napisałem dekorator funkcji, który włącza
goto
w Pythonie, tak po prostu:Nie jestem jednak pewien, dlaczego chciałoby się coś takiego zrobić. To powiedziawszy, nie podchodzę do tego poważnie. Chciałbym jednak zwrócić uwagę, że tego rodzaju metaprogramowanie jest w rzeczywistości możliwe w Pythonie, przynajmniej w CPython i PyPy, i nie tylko przez niewłaściwe użycie interfejsu API debuggera, tak jak zrobił to tamten facet . Musisz jednak zadzierać z kodem bajtowym.
źródło
.begin
i.end
etykiety?Znalazłem to w oficjalnym Pythonie FAQ Design and History .
To bardzo miłe, że jest to nawet wspomniane w oficjalnym FAQ i że dostarczono fajną próbkę rozwiązania. Bardzo lubię Pythona, ponieważ jego społeczność traktuje nawet w
goto
ten sposób;)źródło
goto
pewnością nadużywanie jest poważnym foux pasem programistycznym, ale nadużywanie wyjątków przez IMO w celu emulacjigoto
jest tylko nieznacznie lepsze i nadal powinno być mocno krytykowane. Wolałbym, żeby twórcy Pythona włączyligoto
do języka kilka sytuacji, w których faktycznie jest to użyteczne, niż zablokować go, ponieważ „to jest złe, chłopaki”, a następnie zalecić nadużywanie wyjątków, aby uzyskać tę samą funkcjonalność (i ten sam kod spaghetti).Aby odpowiedzieć na
@ascobol
pytanie użytkownika, korzystając@bobince
z sugestii z komentarzy:Wcięcie
else
bloku jest poprawne. Kod używa niejasnejelse
składni Pythona po pętli. Zobacz Dlaczego python używa „else” po pętli for i while?źródło
else
jest wykonywany po pętli, jeślibreak
nie został napotkany. Efektem jest to, żeshould_terminate_the_loop
zamyka obie pętle wewnętrzne i zewnętrzne.return
sugerowane przez @Jason Baker to dobra alternatywa dla wyrwania się z głęboko zagnieżdżonych pętli.Wykonano działającą wersję: http://entrian.com/goto/ .
Uwaga: był oferowany jako żart primaaprilisowy. (choć działa)
Nie trzeba dodawać że. Tak, to zabawne, ale NIE używaj go.
źródło
Etykiety
break
icontinue
zostały zaproponowane w PEP 3136 w 2007 roku, ale zostały odrzucone. Sekcja Motywacja propozycji ilustruje kilka powszechnych (jeśli nieeleganckich) metod naśladowania oznaczonychbreak
w Pythonie.źródło
Jest technicznie wykonalne, aby dodać do Pythona instrukcję podobną do „goto”. Będziemy używać modułów „dis” i „new”, które są bardzo przydatne do skanowania i modyfikowania kodu bajtowego Pythona.
Główną ideą implementacji jest najpierw oznaczenie bloku kodu za pomocą instrukcji „goto” i „label”. Specjalny dekorator „@goto” będzie używany do oznaczania funkcji „goto”. Następnie skanujemy ten kod w poszukiwaniu tych dwóch instrukcji i wprowadzamy niezbędne modyfikacje do bazowego kodu bajtowego. To wszystko dzieje się w czasie kompilacji kodu źródłowego.
Mam nadzieję, że to odpowiada na pytanie.
źródło
do emulacji można użyć wyjątków zdefiniowanych przez użytkownika
goto
przykład:
źródło
Python 2 i 3
Link: instrukcja goto
foo.py
źródło
Szukałem czegoś podobnego do
Więc moje podejście polegało na użyciu wartości logicznej, aby pomóc wyrwać się z zagnieżdżonych pętli for:
źródło
Jest teraz. iść do
Myślę, że może to być przydatne w przypadku tego, czego szukasz.
źródło
Chciałem tej samej odpowiedzi i nie chciałem używać
goto
. Więc użyłem następującego przykładu (z Learnpythonthehardway)źródło
Mam swój własny sposób robienia rzeczy gotowych. Używam osobnych skryptów Pythona.
Jeśli chcę zapętlić:
plik1.py
plik2.py
plik3.py
( UWAGA: ta technika działa tylko w wersjach Python 2.x)
źródło
W przypadku forward Goto możesz po prostu dodać:
Pomaga to jednak tylko w prostych scenariuszach (np. Zagnieżdżenie ich doprowadziłoby do bałaganu)
źródło
Zamiast odpowiednika goto w Pythonie używam instrukcji break w następujący sposób do szybkich testów mojego kodu. Zakłada się, że masz strukturalną podstawę kodu. Zmienna testowa jest inicjowana na początku twojej funkcji i po prostu przenoszę blok "If test: break" na koniec zagnieżdżonego bloku lub pętli if-then, które chcę przetestować, modyfikując zmienną zwracaną na końcu kodu aby odzwierciedlić testowaną zmienną bloku lub pętli.
źródło
Chociaż nie ma żadnego kodu odpowiadającego temu
goto/label
w Pythonie, nadal możesz uzyskać taką funkcjonalnośćgoto/label
przy użyciu pętli.Weźmy przykładowy kod pokazany poniżej, w którym
goto/label
można go użyć w dowolnym języku innym niż python.Teraz tę samą funkcjonalność powyższego przykładu kodu można osiągnąć w Pythonie za pomocą
while
pętli, jak pokazano poniżej.źródło
nie, istnieje alternatywny sposób implementacji instrukcji goto
źródło