Есть ли goto
или любой эквивалент в Python, чтобы иметь возможность переходить к определенной строке кода?
Есть ли в Python метка / goto?
Ответы (20)
Нет, Python не поддерживает метки и goto, если это то, что вам нужно. Это (высоко) структурированный язык программирования.
Python предлагает вам возможность делать некоторые вещи, которые вы могли бы сделать с помощью goto, используя функции первого класса. Например:
void somefunc(int a)
{
if (a == 1)
goto label1;
if (a == 2)
goto label2;
label1:
...
label2:
...
}
Это можно сделать на питоне так:
def func1():
...
def func2():
...
funcmap = {1 : func1, 2 : func2}
def somefunc(a):
funcmap[a]() #Ugly! But it works.
Конечно, это не лучший способ заменить goto. Но, не зная точно, что вы пытаетесь сделать с goto, сложно дать конкретный совет.
@ ascobol:
Лучше всего либо заключить его в функцию, либо использовать исключение. Для функции:
def loopfunc():
while 1:
while 1:
if condition:
return
За исключением:
try:
while 1:
while 1:
raise BreakoutException #Not a real exception, invent your own
except BreakoutException:
pass
Использование исключений для подобных действий может показаться немного неудобным, если вы пришли с другого языка программирования. Но я бы сказал, что если вам не нравится использование исключений, Python не для вас. :-)
loopfunc
обычно требует ввода и некоторых дополнительных усилий для реализации, но я думаю, что в большинстве случаев это лучший способ.
- person kon psych; 20.05.2016
Недавно я написал декоратор функций, который включает goto
в Python, вот так:
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
Я не уверен, почему кто-то хотел бы делать что-то подобное. Тем не менее, я не слишком серьезно отношусь к этому. Но я хотел бы указать, что этот вид метапрограммирования действительно возможен в Python, по крайней мере, в CPython и PyPy, а не только за счет неправильного использования API отладчика как другой парень сделал. Однако вам придется повозиться с байт-кодом.
.begin
и .end
?
- person Alexej Magura; 10.03.2020
Я нашел это в официальном FAQ по дизайну и истории Python..
Почему нет goto?
Вы можете использовать исключения, чтобы обеспечить «структурированный переход», который работает даже при вызовах функций. Многие считают, что исключения могут удобно имитировать все разумные варианты использования конструкций «go» или «goto» в C, Fortran и других языках. Например:
class label(Exception): pass # declare a label
try:
...
if condition: raise label() # goto label
...
except label: # where to goto
pass
...
Это не позволяет вам перейти в середину цикла, но в любом случае это обычно считается злоупотреблением goto. Используйте экономно.
Очень приятно, что об этом даже упоминается в официальном FAQ и что предоставляется хороший образец решения. Мне очень нравится python, потому что его сообщество так относится даже к goto
;)
goto
- это, безусловно, серьезный недостаток программирования, но ИМО, злоупотребляющее исключениями для имитации goto
, лишь немного лучше и все же должно вызывать осуждение. Я бы предпочел, чтобы создатели Python включали goto
в язык для тех немногих случаев, когда это действительно полезно, чем запрещать его, потому что это плохо, ребята, а затем рекомендовать злоупотреблять исключениями, чтобы получить ту же функциональность (и ту же спагеттификацию кода).
- person Abion47; 09.07.2020
try...except...
для имитации goto (потому что почти все ответы из Интернета предлагают библиотеку python-goto третьей части). Поэтому пытаюсь ответить здесь, пока не увижу этот ответ. Приятно видеть, что это упоминается в официальном документе.
- person bearzyj; 15.05.2021
Чтобы ответить на вопрос @ascobol
, используя предложение @bobince
из комментариев:
for i in range(5000):
for j in range(3000):
if should_terminate_the_loop:
break
else:
continue # no break encountered
break
Отступ для блока else
правильный. В коде используется неясный else
после синтаксиса цикла Python. См. Почему python использует else после циклов for и while?
else
выполняется после цикла, если break
не обнаружен. В результате should_terminate_the_loop
завершает как внутренние, так и внешние циклы.
- person jfs; 07.02.2015
found
, done
болевые переменные.
- person jfs; 07.02.2015
goto
, я бы поспорил с дублированием небольшого фрагмента кода, длина которого не может превышать 10 символов, это не слишком большая натяжка. Цель - удобочитаемость, и проверка if..else с кратким поясняющим комментарием для меня более читабельна, чем цикл, полный довольно непонятного синтаксиса, который может заставить людей подумать, что есть ошибка отступа. Лично, если бы я столкнулся с конкретной необходимостью выйти сразу из нескольких циклов, это о том, как я сделает это.
- person Braden Best; 07.02.2015
return
, предложенный @Jason Baker, является хорошей альтернативой для выхода из глубоко вложенных циклов.
- person jfs; 07.02.2015
goto
. Обычно я обнаружил, что это снижает LOC. плюс то, что что-то считается непонятным синтаксисом, не является причиной не использовать его. вот почему они придумали комментарии #forthewin
- person theEpsilon; 11.01.2020
Создана рабочая версия: http://entrian.com/goto/.
Примечание: это было предложено как первоапрельская шутка. (хотя работает)
# 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"
Разумеется. Да, это забавно, но НЕ используйте это.
Технически возможно добавить в Python оператор типа goto с некоторой работой. Мы будем использовать модули «dis» и «new», оба очень полезны для сканирования и изменения байтового кода Python.
Основная идея реализации состоит в том, чтобы сначала пометить блок кода как использующий операторы «goto» и «label». Для обозначения функций goto будет использоваться специальный декоратор «@goto». После этого мы сканируем этот код на предмет этих двух операторов и вносим необходимые изменения в базовый байтовый код. Все это происходит во время компиляции исходного кода.
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()
Надеюсь, это ответит на вопрос.
Python 2 и 3
pip3 install goto-statement
Протестировано на Python 2.6–3.6 и PyPy.
Ссылка: инструкция goto
foo.py
from goto import with_goto
@with_goto
def bar():
label .bar_begin
...
goto .bar_begin
вы можете использовать определяемые пользователем исключения для имитации goto
пример:
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()
Я искал что-то похожее на
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;
Итак, мой подход состоял в том, чтобы использовать логическое значение, чтобы помочь выйти из вложенных циклов for:
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
Хотя в Python нет кода, эквивалентного goto/label
, вы все равно можете получить такую функциональность goto/label
, используя циклы.
Давайте возьмем пример кода, показанный ниже, где goto/label
можно использовать на любом языке, отличном от 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...')
Теперь те же функциональные возможности, что и в приведенном выше примере кода, могут быть достигнуты в Python с помощью цикла while
, как показано ниже.
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...')
Есть сейчас. goto
Я думаю, это может быть полезно для того, что вы ищете.
Я хотел того же ответа и не хотел использовать goto
. Поэтому я использовал следующий пример (из 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)
У меня есть свой способ делать gotos. Использую отдельные скрипты на Python.
Если я хочу зациклить:
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")
(ПРИМЕЧАНИЕ: этот метод работает только в версиях Python 2.x)
Для прямого Goto вы можете просто добавить:
while True:
if some condition:
break
#... extra code
break # force code to exit. Needed at end of while loop
#... continues here
Это помогает только в простых сценариях (например, их вложение приведет вас в беспорядок)
Вместо эквивалента goto в Python я использую оператор break следующим образом для быстрой проверки моего кода. Это предполагает, что у вас есть структурированная кодовая база. Тестовая переменная инициализируется в начале вашей функции, и я просто перемещаю блок «If test: break» в конец вложенного блока if-then или цикла, который я хочу протестировать, изменяя возвращаемую переменную в конце кода. чтобы отразить переменную блока или цикла, которую я тестирую.
def x:
test = True
If y:
# some code
If test:
break
return something
Вы можете добиться этого, используя вложенные методы внутри Python
def func1():
print("inside func1")
def inline():
print("im inside")
inline()
func1()
нет альтернативного способа реализации инструкции goto
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()
Я думаю, что цикл while является альтернативой goto_Statement. Потому что после 3.6 цикл goto больше не работает. Я также пишу пример цикла while.
str1 = "stop"
while str1 == "back":
var1 = int(input(" Enter Ist Number: "))
var2 = int(input(" Enter 2nd Number: "))
var3 = print(""" What is your next operation
For Addition Press And Enter : 'A'
For Muliplt Press And Enter : 'M'
For Division Press And Enter : 'D'
For Subtaction Press And Enter : 'S' """)
var4 = str(input("For operation press any number : "))
if(var1 == 45) and (var2 == 3):
print("555")
elif(var1 == 56) and (var2 == 9):
print("77")
elif(var1 == 56) and (var2 == 6):
print("4")
else:
if(var4 == "A" or "a"):
print(var1 + var2)
if(var4 == "M" or "m"):
print(var1 * var2)
if(var4 == "D" or "d"):
print(var1 / var2)
if(var4 == "S" or "s"):
print(var1 - var2)
print("if you want to continue then type 'stop'")
str1 = input()
print("Strt again")
goto
на Python, когда переводил некоторый код Fortran на Python. Он ненавидел себя за это. - person Cody Piersall   schedule 26.05.2014