当前位置:  开发笔记 > 编程语言 > 正文

Python中有标签/ goto吗?

如何解决《Python中有标签/goto吗?》经验,为你挑选了8个好方法。

gotoPython中是否有一个或任何等价物能够跳转到特定的代码行?



1> unwind..:

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


@rejinacm的功能?
将代码重构为函数并执行返回

2> Jason Baker..:

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> Sebastian No..:

我最近写了一个函数装饰器,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> klaas..:

我在官方的python设计和历史常见问题中找到了这个.

为什么没有转到?

您可以使用异常来提供甚至可以跨函数调用工作的"结构化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> jfs..:

使用评论中的建议回答@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'?


@ B1KMusic:缩进是正确的.这是一种特殊的Python语法.如果没有遇到`break`,则在循环*之后执行`else`.结果是`should_terminate_the_loop`终止了*内部和外部循环.

6> harmv..:

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

不用说.是的它有趣,但不要使用它.



7> Bill the Liz..:

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



8> Rabih Kodeih..:

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

希望这能回答这个问题.

推荐阅读
谢谢巷议
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有