2004-04-04 · in Ideas · 322 words

The goto for Python module implements the "goto" and "label" keywords in Python. It's intended as a joke, but their first example is something I actually want to do occasionally in Python: break out of nested loops.

for x in list1:
  for y in list2:
    if condition:
      goto .exit
label .exit

Most other languages provide some way to exit from nested loops. Perl has labelled blocks; C has goto. The approach I'd normally use in Python (if there wasn't a nicer way to reorganise it) would be to wrap a function around it.

def function():
  for x in list1:
    for y in list2:
      if condition:
        return
function()

You could also wrap the block in a try and throw an exception to exit, although that's more code (and less semantically sensible — you shouldn't use exceptions for routine conditions). Similarly, if Python had an equivalent of Scheme's call/cc, you could use a continuation to exit the block.

There are several possible syntaxes for labelled loops in Python (assuming break were extended to accept a label, so break outer would exit the loop labelled outer). A suitably general syntax would allow you to label any code block for a later break or continue.

for x in list1 named outer:
outer:: for x in list1:
for outer where x in list1:
for (outer) x in list1:
for x in list1 :: outer:
  ...
  break outer

A simpler approach that'd work for for loops would be to let the break statement take a loop variable. This wouldn't allow you to break out of nested while loops, but that may not be a problem.

for x in list1:
  ...
  break x

A final approach would be to allow break to take a numeric argument indicating how many levels of indentation to exit; this has the advantage of being very simple, but it seems unlikely to lead to readable code.

(Most of this came out of an IRC discussion with Giles Radford.)