Python 中有标签/goto 吗?

2024-12-30 08:42:00
admin
原创
77
摘要:问题描述:Python 中是否有goto可以跳转到特定代码行的函数?解决方案 1:不,Python 不支持标签和 goto。它是一种(高度)结构化的编程语言。解决方案 2:Python 让你能够使用一流函数执行一些使用 goto 可以完成的操作。例如:void somefunc(int a) { if...

问题描述:

Python 中是否有goto可以跳转到特定代码行的函数?


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

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

解决方案 3:

我最近写了一个在 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 中是可能的,而不仅仅是像其他人那样滥用调试器 API 。不过,你必须弄乱字节码。

解决方案 4:

我在官方的 Python 设计和历史常见问题解答中找到了这一点。

为什么没有 goto?

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

class label(Exception): pass  # declare a label

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

这不允许您跳转到循环中间,但这通常被认为是对 goto 的滥用。请谨慎使用。

官方常见问题解答中甚至提到了这一点,并且提供了一个很好的解决方案示例,这非常好。我真的很喜欢 Python,因为它的社区甚至如此对待goto它 ;)

解决方案 5:

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

不用说。是的,这很有趣,但不要使用它。

解决方案 6:

使用评论中的建议来回答@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 在 for 和 while 循环后使用“else”?

解决方案 7:

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

解决方案 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:

早在 2007 年, PEP 3136就提出了break和的标签,但被否决了。该提案的动机部分说明了在 Python 中模仿标签的几种常见(尽管不够优雅)方法。continue`break`

解决方案 10:

您可以使用用户定义的异常来模拟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:

在实现“goto”时,首先要问什么是 goto。虽然这看起来很明显,但大多数人并没有考虑 goto 与函数堆栈有何关系。

如果您在函数内部执行“goto”,则实际上会放弃函数调用堆栈。这被认为是不好的做法,因为函数堆栈的设计期望您在委托中间任务后继续执行上次中断的操作。这就是为什么 goto 用于异常的原因,而异常可用于模拟 goto,我将对此进行解释。

有限状态机可能是 goto 的最佳用例,大多数情况下 goto 都是用循环和 switch 语句以笨拙的方式实现的,但我相信“顶级” goto 是实现有限状态机最干净、最语义化的方式。在这种情况下,您要确保,如果您有更多变量,它们是全局变量,并且不需要封装。确保您首先对变量状态空间进行建模(这可能与执行状态不同,即有限状态机)。

我认为使用 goto 有合理的设计理由,异常处理是将 goto 与函数混合使用的特殊情况。但是,在大多数情况下,您希望将自己限制在“顶级”goto 中,因此您永远不会在函数内调用 goto,而只能在全局范围内调用 goto。

在现代语言中模拟顶层 goto 的最简单方法是认识到顶层 goto 只需要全局变量和一个空的调用堆栈。因此,为了保持调用堆栈为空,每当调用新函数时都要返回。以下是打印前 n 个斐波那契数的示例:

a = 0
b = 1
n = 100
def A():
    global a, b
    a = a + b
    n -= 1
    print(a)
    return B() if n > 0 else 0
def B():
    global a, b
    b = a + b
    n -= 1
    print(b)
    return A() if n > 0 else 0
A()

虽然此示例可能比循环实现更冗长,但它也更强大、更灵活,并且不需要特殊情况。它让您拥有一个完整的有限状态机。您还可以使用 goto 运行器对其进行修改。

def goto(target):
    while(target) target = target()
def A():
    global a, b
    a = a + b
    print(a)
    return B
def B():
    global a, b
    b = a + b
    print(b)
    return A
goto(A)

为了强制“返回”部分,您可以编写一个 goto 函数,当完成时只需抛出异常。

def goto(target):
    target()
    throw ArgumentError("goto finished.")
def A():
    global a, b
    a = a + b
    print(a)
    goto(B)
def B()
    global a, b
    b = a + b
    print(b)
    goto(A)
goto(A)

所以你看,很多都是想多了,一个调用函数然后抛出错误的辅助函数就是你所需要的。你可以进一步将其包装在“start”函数中,这样错误就会被捕获,但我认为这不是绝对必要的。虽然其中一些实现可能会耗尽你的调用堆栈,但第一个运行器示例会将其保持为空,如果编译器可以进行尾部调用优化,那也会有所帮助。

解决方案 12:

我正在寻找类似的东西

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

解决方案 13:

虽然没有与goto/labelPython 中等效的代码,但您仍然可以获得goto/label使用循环的此类功能。

让我们看下面显示的一个代码示例,其中goto/label可以在除 Python 之外的任意语言中使用。

String str1 = 'BACK'

label1:
    print('Hello, this program contains goto code
')
    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
Bla bla bla...
Bla bla bla...
Bla bla bla...')

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

str1 = 'BACK'

while str1 == 'BACK':
        print('Hello, this is a python program containing python equivalent code for goto code
')
        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
Bla bla bla...
Bla bla bla...
Bla bla bla...')

解决方案 14:

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

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

解决方案 15:

现在有了。转到

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

解决方案 16:

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

解决方案 17:

我有自己的执行 goto 的方法。我使用单独的 python 脚本。

如果我想循环:

文件1.py

print("test test")
execfile("file2.py")
a = a + 1

文件2.py

print(a)
if a == 10:
   execfile("file3.py")
else:
   execfile("file1.py")

文件3.py

print(a + " equals 10")

注意:此技术仅适用于 Python 2.x 版本)

解决方案 18:

对于前向 Goto,您只需添加:

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

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

解决方案 19:

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

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

解决方案 20:

没有,有另一种方法来实现 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      age")
                        for i in range(n):
                            print(name[i],"      ",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      age")
                for i in range(n):
                    print(name[i],"      ",age[i])
                n=-1
p1=id()
p1.data1()  

解决方案 21:

我认为您可以在代码中创建函数,如果某些条件为真,您可以直接调用该函数,而不是使用 goto。

解决方案 22:

我认为 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")    
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1008  
  在项目管理中,变更是一个不可避免的现象。无论是客户需求的调整、市场环境的变化,还是技术方案的更新,都可能引发项目的变更。如果处理不当,这些变更可能会导致项目延期、成本超支,甚至项目失败。因此,如何有效地应对项目变更,成为项目管理中的核心挑战之一。IPD(集成产品开发)作为一种高效的项目管理方法,其流程图不仅能够帮助团队...
IPD流程中的charter   0  
  IPD(Integrated Product Development,集成产品开发)是华为在长期实践中总结出的一套高效产品开发管理体系。它不仅帮助华为在全球市场中脱颖而出,也成为许多企业提升产品开发效率的参考标杆。IPD的核心在于通过跨部门协作、流程优化和资源整合,实现从需求分析到产品交付的全生命周期管理。通过实施IP...
IPD开发流程管理   0  
  华为IPD(集成产品开发)流程是一种以客户需求为导向、跨部门协同的高效项目管理方法。它通过系统化的流程设计和严格的阶段控制,确保项目从概念到交付的每个环节都能高效运作。IPD流程的核心在于打破传统职能部门的壁垒,将产品开发、市场、销售、供应链等关键环节整合到一个统一的框架中,从而实现资源的优化配置和信息的无缝流动。这种...
IPD流程中TR   0  
  在项目管理的实践中,CDCP(Certified Data Center Professional)认证评审是一个至关重要的环节。通过这一评审,项目团队不仅能够验证其数据中心设计和运营的合规性,还能提升整体管理水平。为了确保评审的顺利进行,准备一系列关键文档是必不可少的。这些文档不仅是评审的依据,也是项目团队与评审专家...
华为IPD是什么   0  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用