Есть ли метка /goto в Python?

Есть ли goto или любой эквивалент в Python, чтобы иметь возможность перейти к определенной строке кода?

Ответ 1

Нет, Python не поддерживает метки и goto, если это то, что вам нужно. Это (высоко) структурированный язык программирования.

Ответ 2

Python предлагает вам возможность выполнять некоторые действия, которые вы можете сделать с помощью goto, используя функции первого класса. Например:

void somefunc(int a)
{
    if (a == 1)
        goto label1;
    if (a == 2)
        goto label2;

    label1:
        ...
    label2:
        ...
}

Может быть сделано в python следующим образом:

def func1():
    ...

def func2():
    ...

funcmap = {1 : func1, 2 : func2}

def somefunc(a):
    funcmap[a]()  #Ugly!  But it works.

Конечно, это не лучший способ заменить goto. Но, не зная точно, что вы пытаетесь сделать с goto, трудно дать конкретные советы.

@аскобол:

Лучше всего либо заключить его в функцию, либо использовать исключение. Для функции:

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 не является для вас языком.: -)

Ответ 3

Недавно я написал декоратор функций, который позволяет 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 отладчика в качестве другого парня сделал. Вы должны возиться с байт-кодом, хотя.

Ответ 4

Я нашел это в официальном FAQ по настройке и истории python.

Почему нет goto?

Вы можете использовать исключения, чтобы обеспечить "структурированную перестановку", которая даже работает через вызовы функций. Многие считают, что исключения могут подражать всем разумным применениям конструкций "go" или "goto" C, Фортране и других языках. Например:

class label(Exception): pass  # declare a label

try:
    ...
    if condition: raise label()  # goto label
    ...
except label:  # where to goto
    pass
... 

Это не позволяет вам прыгать в середину цикла, но thats обычно считается злоупотреблением goto. Используйте экономно.

Очень приятно, что это даже упоминается в официальном FAQ, и что предоставляется хороший образец решения. Мне очень нравится python, потому что его сообщество обрабатывает даже goto как это;)

Ответ 5

Чтобы ответить на вопрос @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?

Ответ 6

Сделана рабочая версия: 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"

Нет нужды говорить. Да, это смешно, но DONT его использовать.

Ответ 7

Ярлыки для break и continue были предложены в Motivation иллюстрирует несколько общих (если неэлегантных) методов имитации помеченных break в Python.

Ответ 8

Технически возможно добавить инструкцию 'goto' на python с некоторой работой. Мы будем использовать модули "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()

Надеюсь, что это ответит на вопрос.

Ответ 9

вы можете использовать Пользовательские исключения для эмуляции 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()

Ответ 10

Я искал нечто похожее на

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 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

Ответ 11

Сейчас. goto

Я думаю, что это может быть полезно для того, что вы ищете.

Ответ 12

Мне нужен тот же ответ, и я не хотел использовать goto. Поэтому я использовал следующий пример (из учебного плана)

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)

Ответ 13

У меня есть свой способ делать 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)

Ответ 14

Для форвард Гото, вы можете просто добавить:

while True:
  if some condition:
    break
  #... extra code
  break # force code to exit. Needed at end of while loop
#... continues here

Это помогает только для простых сценариев (то есть, их вложение приведет вас в беспорядок)

Ответ 15

Вместо эквивалента Python Goto я использую оператор break следующим образом для быстрых тестов моего кода. Это предполагает, что у вас есть структурированная кодовая база. Тестовая переменная инициализируется в начале вашей функции, и я просто перемещаю блок "If test: break" в конец вложенного блока if-then или цикла, который я хочу проверить, изменяя возвращаемую переменную в конце кода чтобы отразить блочную или циклическую переменную, которую я тестирую.

def x:
  test = True
  If y:
     # some code
     If test:
            break
  return something

Ответ 16

нет, есть альтернативный способ реализации оператора 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()  

Ответ 17

Python 2 & 3

pip3 install goto-statement

Протестировано на Python 2.6 - 3.6 и PyPy.

Ссылка: goto-Statement


foo.py

from goto import with_goto

@with_goto
def bar(start, stop):

    label .bar_begin

    ...

    goto .bar_begin

Ответ 18

В Python оператор goto поддерживается с помощью goto.<label_name> и label.<label_name>. Для получения дополнительной информации перейдите по этой ссылке.

def func():
    resp = call_something()
    if resp != 0: # Failure case
        goto .failure_handler

    ....
    ....
    resp = ....
    if resp != 0: # Failure case
        goto .failure_handler

    ....
    ....    

    label .failure_handler
    cleanup
    return -1   

Обычно на всей планете люди рекомендуют избегать использования оператора goto. Но обработка ошибок в функции может быть хорошо обработана только с помощью оператора goto. Даже я не предпочитаю использовать goto, кроме обработчика сбоев.