Y a-t-il un label/goto en Python?

y a-t-il un goto ou un équivalent en Python pour pouvoir sauter à une ligne de code spécifique?

124
demandé sur Mu Mind 2009-01-13 15:53:23

15 réponses

Non, Python ne supporte pas les labels et goto, si c'est ce que vous recherchez. C'est un langage de programmation (hautement) structuré.

88
répondu unwind 2009-01-13 12:55:57

Python vous offre la possibilité de faire certaines des choses que vous pourriez faire avec un goto utilisant des fonctions de première classe. Par exemple:

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

    label1:
        ...
    label2:
        ...
}

pourrait être fait en python comme ceci:

def func1():
    ...

def func2():
    ...

funcmap = {1 : func1, 2 : func2}

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

Accordée, ce n'est pas la meilleure façon de remplacer goto. Mais sans savoir exactement ce que vous essayez de faire avec le goto, il est difficile de donner des conseils spécifiques.

@ ascobol :

Votre meilleur pari est de l'enfermer dans une fonction ou d'utiliser une exception. Pour la fonction:

def loopfunc():
    while 1:
        while 1:
            if condition:
                return

pour l'exception:

try:
    while 1:
        while 1:
            raise BreakoutException #Not a real exception, invent your own
except BreakoutException:
    pass

utiliser des exceptions pour faire des choses comme ça peut sembler un peu embarrassant si vous venez d'un autre langage de programmation. Mais je dirais que si vous n'aimez pas les exceptions, Python n'est pas le langage pour vous. :- )

63
répondu Jason Baker 2017-05-23 12:18:22

j'ai récemment , a écrit une fonction décorateur qui permet de goto en Python, juste comme ça:

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

je ne sais pas pourquoi on voudrait faire quelque chose comme cela. Cela dit, je ne suis pas trop sérieux à son sujet. Mais je tiens à souligner que ce genre de méta-programmation est possible en Python, du moins en CPython et PyPy, et pas seulement en utilisant l'API de déboguage de manière erronée comme l'a fait "l'autre type . Vous avoir à jouer avec le bytecode.

30
répondu Sebastian Noack 2015-09-20 20:15:04

Pour répondre au @ascobol 'à la question à l'aide @bobince suggestion de la part de vos commentaires:

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

le tiret du bloc else est correct. Le code utilise l'obscur else après une syntaxe de Python en boucle. Voir Pourquoi python utilisation 'd'autre' après les boucles for et while?

15
répondu jfs 2018-01-23 08:54:12

j'ai trouvé ceci dans le conception officielle de python et L'histoire FAQ .

pourquoi il n'y a pas de goto?

vous pouvez utiliser des exceptions pour fournir un "Goto structuré" qui fonctionne même à travers des appels de fonction. Beaucoup estiment que les exceptions peuvent être imiter toutes les utilisations raisonnables des constructions" go "ou" goto " de C, Fortran, et d'autres langues. Par exemple:

class label(Exception): pass  # declare a label

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

Cela ne vous permet pas de vous sauter au milieu d'une boucle, mais c'est généralement considéré comme un abus de goto de toute façon. À utiliser avec parcimonie.

il est très agréable que cela soit même mentionné dans la FAQ officielle, et qu'un bel échantillon de solution soit fourni. J'aime vraiment python parce que sa communauté traite même goto comme ceci;)

13
répondu klaas 2017-06-28 00:21:43

une version de travail a été réalisée: http://entrian.com/goto / .

Note:il a été offert comme une blague de poisson d'avril. (de travail)

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

inutile de dire. Oui, c'est drôle, mais ne l'utilisez pas.

9
répondu harmv 2015-05-21 12:09:07
Les étiquettes

pour break et continue ont été proposées dans PEP 3136 en 2007, mais elles ont été rejetées. La section Motivation de la proposition illustre plusieurs méthodes courantes (si inélégantes) pour imiter break en Python.

7
répondu Bill the Lizard 2012-03-26 22:03:09

il est techniquement possible d'ajouter une déclaration de type 'goto' à python avec un peu de travail. Nous utiliserons les modules" dis "et" new", tous deux très utiles pour numériser et modifier le code octet python.

l'idée principale derrière la mise en œuvre est de marquer d'abord un bloc de code en utilisant des instructions" goto "et" label". Un décorateur spécial" @goto "sera utilisé pour marquer les fonctions" goto". Ensuite, nous scannons ce code pour ces deux énoncés et appliquons le les modifications nécessaires au code octet sous-jacent. Tout cela se produit au moment de la compilation du code source.

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

espérons que cela réponde à la question.

6
répondu Rabih Kodeih 2015-06-17 00:15:41

je cherchais quelque chose de similaire à

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;

donc mon approche était d'utiliser un booléen pour aider à sortir de la boucle emboîtée:

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
3
répondu yaitloutou 2016-07-07 06:28:25

vous pouvez utiliser Exceptions définies par L'utilisateur pour émuler goto

exemple:

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()
2
répondu xavierskip 2015-03-27 16:07:25

je voulais la même réponse et je ne voulais pas utiliser goto . J'ai donc utilisé l'exemple suivant (tiré de 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)
1
répondu san1512 2015-07-30 14:28:19

il y en a maintenant. goto

je pense que cela pourrait être utile pour ce que vous recherchez.

1
répondu ancho 2015-09-22 06:33:52

j'ai ma propre façon de faire Goto. J'utilise des scripts python séparés.

si je veux boucler:

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

( NOTE: cette technique ne fonctionne que sur Python 2.X versions)

1
répondu Anonaguy 2018-05-04 17:25:49

dans la déclaration Goto de Python est supporté par goto .<label_name> et label .<label_name> . Pour plus d'informations s'il vous plaît aller à travers ce lien .

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   

généralement sur toute la planète, les gens recommandent d'éviter d'utiliser la déclaration goto. Mais une manipulation de défaillance dans une fonction peut être bien gérée avec seulement la déclaration goto. Même Je ne préfère pas l'utilisation de goto autre que le handler de défaillance.

0
répondu rashok 2018-03-01 15:11:47

pour un Goto avant, vous pouvez juste ajouter:

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

cela n'aide que pour les scénarios simples (c'est-à-dire que l'imbrication de ceux-ci vous mettrait dans une situation confuse)

0
répondu JGFMK 2018-06-02 18:53:30