Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

`goto` in Python

I must use goto in Python. I found entrians goto but my Python implementation (CPython 2.7.1 on Mac) does not have this module, so it doesn't seem to be portable. It should at least work in all Python implementations which support CPython bytecode (esp. I care about CPython and PyPy). Then there is this related question, and cdjc's goto. And the ones given by answers below.

I could go and build up the bytecode manually (i.e. write my own Python compiler) because there is such an instruction (JUMP_ABSOLUTE and friends). But I wonder if there is an easier way. Is it possible via inspect or so to call a single bytecode instruction? I also thought about compiling via Python and then automatically patching the generated Python bytecode.


Of course, people will ask why and will not give me any helpful answer if I don't explain why I really really need this. So in short my use case: I am translating a C AST to Python AST and compiling this. I can map every logical flow (all the loops and other stuff) in some way to equivalent Python code. Everything except goto. Related projects: PyCParser (see interpreter.py), PyCPython, PyLua.

like image 205
Albert Avatar asked Aug 05 '11 16:08

Albert


People also ask

Is there a goto in Python?

No, Python does not support labels and goto. It's a (highly) structured programming language.

What is goto statement in Python?

When you use a goto statement in Python, you are basically instructing the interpreter to directly execute another line of code instead of the current one. The target line of code which you want the interpreter to execute at this moment needs to be marked in the section termed “label”.

How do you write goto in Python?

There's no goto instruction in the Python programming language. You'll have to write your code in a structured way... But really, why do you want to use a goto ? that's been considered harmful for decades, and any program you can think of can be written without using goto .

What can I use instead of goto in Python?

Python does not support goto or anything equivalent. You should check out the control flow page for more information. In many other cases, you'll want to use a function to handle the logic you want to use a goto statement for. Show activity on this post. You can use infinite loop, and also explicit break if necessary.


2 Answers

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

@goto def 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:

  • https://github.com/cdjc/goto
  • https://github.com/snoack/python-goto
like image 65
Paolo Moretti Avatar answered Sep 26 '22 19:09

Paolo Moretti


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):     pass  try:     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.

like image 40
kindall Avatar answered Sep 22 '22 19:09

kindall