Python中有标签/ goto吗?

时间:2009-01-13 12:53:23

标签: python goto

Python中是否有goto或任何等价物才能跳转到特定的代码行?

20 个答案:

答案 0 :(得分:97)

不,Python不支持标签和转到,如果这是您所追求的。它是一种(高度)结构化的编程语言。

答案 1 :(得分:65)

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做什么,很难给出具体的建议。

@ 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就不适合您。 : - )

答案 2 :(得分:38)

我最近wrote a function decorator在Python中启用了goto,就像那样:

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中,并且不仅仅是因为other guy误用了调试器API。你必须弄乱字节码。

答案 3 :(得分:20)

我在official python Design and History FAQ中找到了这个。

  

为什么没有转到?

     

您可以使用例外来提供甚至有效的“结构化goto”   跨函数调用。许多人认为异常可以很方便   模仿C的“go”或“goto”结构的所有合理用法,   Fortran等语言。例如:

class label(Exception): pass  # declare a label

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

这不允许你跳到循环的中间,但那是   通常认为滥用goto无论如何。谨慎使用。

在官方常见问题解答中甚至提到这一点非常好,并且提供了一个很好的解决方案示例。我真的很喜欢python,因为它的社区甚至会像这样处理goto;)

答案 4 :(得分:15)

使用评论中的@bobince建议回答@ascobol's question

for i in range(5000):
    for j in range(3000):
        if should_terminate_the_loop:
           break
    else: 
        continue # no break encountered
    break

else块的缩进是正确的。在循环Python语法之后,代码使用了模糊的else。见Why does python use 'else' after for and while loops?

答案 5 :(得分:12)

已经制作了一个工作版本: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"

毋庸置疑。是的,这很有趣,但不要使用它。

答案 6 :(得分:7)

breakcontinue的标签于2007年在PEP 3136提出,但遭到拒绝。该提案的Motivation部分说明了在Python中模仿标记为break的几种常见(如果不优雅)方法。

答案 7 :(得分:7)

通过一些工作向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()

希望这能回答这个问题。

答案 8 :(得分:3)

我正在寻找类似于

的东西
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

答案 9 :(得分:2)

现在有。 goto

我认为这可能对您正在寻找的内容有用。

答案 10 :(得分:2)

您可以使用User-defined Exceptions模仿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()

答案 11 :(得分:2)

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

答案 12 :(得分:1)

我想要相同的答案,我不想使用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)

答案 13 :(得分:1)

我有自己的做事方法。 我使用单独的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 :(得分:0)

对于转发转到,你可以添加:

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

这仅对简单的场景有帮助(即嵌套这些会让你陷入混乱)

答案 15 :(得分:0)

代替python goto等效项,我以以下方式使用break语句对我的代码进行快速测试。假定您具有结构化的代码库。测试变量在函数开始时初始化,我只是将“ If test:break”块移到要测试的嵌套if-then块或循环的末尾,在代码末尾修改了返回变量反映我正在测试的块或循环变量。

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

答案 16 :(得分:0)

没有实现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 :(得分:0)

尽管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...')

现在,可以通过使用while循环在python中实现上述代码示例的相同功能,如下所示。

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...')

答案 18 :(得分:0)

我认为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")    

答案 19 :(得分:0)

你可以使用python中的嵌套方法来实现

def func1():
    print("inside func1")
    def inline():
        print("im inside")
    
    inline()
    
func1()