`goto` in Python `goto` in Python python python

`goto` in Python


I know what everybody is thinking:

xkcd GOTO

However, there might be some didactic cases where you actually need a goto.

This python recipe provides the goto command as a function decorator.

The goto decorator (Python recipe by Carl Cerecke)

This is the recipe for you if you are sick of the slow speed of the existing goto module http://entrian.com/goto/. The goto in this recipe is about 60x faster and is also cleaner (abusing sys.settrace seems hardly pythonic). Because this is a decorator, it alerts the reader which functions use goto. It does not implement the comefrom command, although it is not difficult to extend it to do so (exercise for the reader). Also, computed gotos aren't supported; they're not pythonic.

  • Use dis.dis(fn) to show the bytecode disassembly of a function.
  • The bytecodes of a function are accessed by fn.func_code.co_code. This is readonly so:
  • The decorated function is created exactly the same as the old one, but with the bytecode updated to obey the goto commands.
  • This is 2.x only; the new module is not in python 3.x (another exercise for the reader!)

Usage

@gotodef test1(n):    s = 0    label .myLoop    if n <= 0:        return s    s += n    n -= 1    goto .myLoop>>> test1(10)55

Update

Here're two additional implementations compatible with Python 3:


You may have the only valid use case I have ever seen for needing goto in Python. :-)

The most straightforward way to emulate forward goto in Python is using exceptions, as these can jump out of any depth of nested control structures.

class Goto(Exception):    passtry:    if foo = "bar":        raise Goto    print "foo is not bar"except Goto:    print "foo is bar"

This gets hairy if you need to support more than one destination, but I think it could be done using nested try/except structures and multiple classes of exception, one for each destination. Since C limits goto to the scope of a single function, at least you won't have to worry about how to make this work across functions. :-) Of course, it doesn't work for reverse gotos.

Another thing to note is that exceptions in Python, while fast compared to some languages, are still slower than normal flow control structures such as while and for.

This could be a lot of work (though perhaps not more than you're already in for), but if you could generate Python bytecode rather than Python source, you would have no problem implementing goto, because Python bytecode (like most psuedo-machine-languages) has a perfectly cromulent JUMP_ABSOLUTE opcode.


I've updated my python goto decorator for Python 3. You can get it at https://github.com/cdjc/goto. Using goto instead of functions can make a state machine about 5 times faster.

The version for python 2 is still available at http://code.activestate.com/recipes/576944-the-goto-decorator/ but it has a number of bugs that are fixed in the python 3 version.