265 votes

Existe-t-il un label/goto en Python ?

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

3 votes

L'étiquette est assez vague. Pouvez-vous être plus précis sur ce que vous recherchez ?

16 votes

25 votes

Un de mes amis a mis en place goto en Python alors qu'il traduisait du code Fortran en Python. Il s'est détesté pour ça.

17voto

J.F. Sebastian Points 102961

Pour répondre à la @ascobol La question de la Commission en utilisant @bobince dans les commentaires :

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

L'indentation pour le else est correct. Le code utilise l'obscurité else après une boucle syntaxe Python. Voir Pourquoi python utilise-t-il 'else' après les boucles for et while ?

0 votes

J'ai corrigé l'indentation de votre autre bloc, ce qui a conduit à un découverte intéressante :

4 votes

@B1KMusic : l'indentation est correcte telle quelle. Il s'agit d'une syntaxe spéciale de Python. else est exécuté après la boucle si break n'a pas été rencontré. L'effet est que should_terminate_the_loop met fin à les deux les boucles intérieures et extérieures.

1 votes

J'aurais dû préciser que je n'ai fait cette découverte qu'après avoir fait l'édition. Avant cela, je pensais avoir découvert un bug dans l'interpréteur, j'ai donc fait un tas de cas de test et a fait quelques recherches pour comprendre ce qui se passait. Désolé pour ça.

13voto

user698585 Points 3019

Il est techniquement possible d'ajouter une instruction de type 'goto' à python avec un peu de travail. Nous utiliserons les modules "dis" et "new", tous deux très utiles pour analyser et modifier le byte code de python.

L'idée principale de l'implémentation est de marquer un bloc de code comme utilisant des instructions "goto" et "label". Un décorateur spécial "@goto" sera utilisé dans le but de marquer les fonctions "goto". Ensuite, nous analysons le code à la recherche de ces deux instructions et appliquons les modifications nécessaires au code octet sous-jacent. Tout cela se passe 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()

J'espère que cela répond à votre question.

0 votes

Grande fonction utilitaire ! ( goto() ) Cela fonctionne bien pour moi. Mais uniquement dans Python 2. Lorsqu'il est utilisé dans Python 3, il y a de nombreuses exceptions (par exemple new Le module Py 3 est remplacé par types , .func_code. remplacé par .__code__. etc). Ce serait formidable si vous pouviez adopter cette fonction pour Python 3.

13voto

Marco D.G. Points 635

Python 2 et 3

pip3 install goto-statement

Testé sur Python 2.6 à 3.6 et PyPy.

Lien : déclaration de goto


foo.py

from goto import with_goto

@with_goto
def bar():

    label .bar_begin

    ...

    goto .bar_begin

8voto

xavierskip Points 356

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

0 votes

Méthode géniale mais peut-on mettre en sourdine l'exception str m méthode

0 votes

@Anonymous quelle exception ? vous utilisez python3 ?

8voto

Bill the Lizard Points 147311

Étiquettes pour break et continue ont été proposés dans PEP 3136 en 2007, mais elle a été rejetée. Le site Motivation La section de la proposition illustre plusieurs méthodes courantes (bien qu'inélégantes) d'imitation de l'image de marque. break en Python.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X