240

goto特定のコード行にジャンプできるようにするために、Pythonに同等のものはありますか?

4

21 に答える 21

157

いいえ、Python はラベルと goto をサポートしていません。これは (高度に) 構造化されたプログラミング言語です。

于 2009-01-13T12:55:57.930 に答える
100

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 はあなたのための言語ではないと私は主張します。:-)

于 2009-01-13T13:04:56.727 に答える
92

私は最近、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 を誤用するだけではないことを指摘したいと思います。ただし、バイトコードをいじる必要があります。

于 2015-09-20T20:15:04.517 に答える
47

これは、公式の python Design and History FAQで見つけました。

なんで後藤がないの?

例外を使用して、関数呼び出し間でも機能する「構造化された 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 の乱用と見なされます。控えめに使用してください。

これが公式の FAQ にも記載されており、すばらしい解決策のサンプルが提供されていることは非常に素晴らしいことです。コミュニティがこのように扱っているので、私はPythonが本当に好きgotoです;)

于 2017-01-20T16:40:03.950 に答える
16

コメントからの提案を使用して@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」を使用するのはなぜですか?を参照してください。

于 2009-01-17T17:42:56.797 に答える
13

「goto」のようなステートメントを python に追加することは、技術的に実行可能です。「dis」モジュールと「new」モジュールを使用します。どちらも Python バイト コードのスキャンと変更に非常に役立ちます。

実装の背後にある主なアイデアは、最初に「goto」ステートメントと「label」ステートメントを使用してコードのブロックをマークすることです。「goto」関数をマークする目的で、特別な「@goto」デコレータが使用されます。その後、これら 2 つのステートメントのコードをスキャンし、基になるバイト コードに必要な変更を適用します。これはすべて、ソース コードのコンパイル時に発生します。

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

これが質問に答えることを願っています。

于 2015-05-05T10:36:10.190 に答える
8

breakとのラベルは 2007 年にPEP 3136continueで提案されましたが、却下されました。提案の動機セクションでは、Python でラベル付けされたものを模倣するためのいくつかの一般的な (洗練されていない場合) メソッドを示しています。break

于 2012-03-26T22:03:09.047 に答える
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
于 2016-07-07T06:23:05.480 に答える
3

Python に相当するコードはありませんが、ループを使用する goto/labelことでそのような機能を得ることができます。goto/label

goto/labelPython 以外の任意の言語で使用できる、以下に示すコード サンプルを見てみましょう。

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...')
于 2019-12-15T18:13:51.070 に答える
2

今ある。後藤

これはあなたが探しているものに役立つかもしれないと思います。

于 2015-09-22T06:33:52.677 に答える
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)
于 2015-07-30T14:28:19.640 に答える