Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I wanted to know if there are any built-in ways to continue to next iteration in outer loop in python. For example, consider the code:

for ii in range(200):
    for jj in range(200, 400):
        ...block0...
        if something:
            continue
    ...block1...

I want this continue statement to exit the jj loop and goto next item in the ii loop. I can implement this logic in some other way (by setting a flag variable), but is there an easy way to do this, or is this like asking for too much?

There actually exists a working goto statement for Python: entrian.com/goto. It was released as an April fool's joke :-), but is supposed to work. – codeape Dec 7, 2009 at 10:17 Oh, please don't use that goto joke! It's remarkably clever, but you will be sad later if you put it into your code. – Ned Batchelder Dec 7, 2009 at 13:35 I'm pretty sure this is considered by many to be one of the very very few valid use cases of goto, see here: stackoverflow.com/questions/24451/…. – Sidharth Ghoshal Mar 18 at 19:19 Hi, are there any other options like this? Because I want to do another for loop in block1, and like that my code would go 3 levels deep. Weird situation. – Sahas Dec 7, 2009 at 10:24 To me this sounds like you are trying to do something with for loops that would be best approached in a different way... – Kimvais Dec 7, 2009 at 10:27 Yes. That's why I didn't use the for..else structure. Now I'd still need for loops, but I'll use flag variables to divert control. – Sahas Dec 7, 2009 at 11:10 for...else is often a useful construct, though it can be confusing. Just remember that else means "no break" in this context. – asmeurer Mar 24, 2014 at 18:38 This seems to be limited to just two layers of loops. I need to update some code which has three nested loops, and a new customer requirement means that under certain circumstances the innermost loop need to continue next iteration of the outermost loop. I assume your suggestion would not apply to that scenario. – kasperd Apr 25, 2016 at 12:29

In a general case, when you have multiple levels of looping and break does not work for you (because you want to continue one of the upper loops, not the one right above the current one), you can do one of the following

Refactor the loops you want to escape from into a function

def inner():
    for j in ...:
        for k in ...:
            if something:
                return
for i in ...:
    inner()

The disadvantage is that you may need to pass to that new function some variables, which were previously in scope. You can either just pass them as parameters, make them instance variables on an object (create a new object just for this function, if it makes sense), or global variables, singletons, whatever (ehm, ehm).

Or you can define inner as a nested function and let it just capture what it needs (may be slower?)

for i in ...:
    def inner():
        for j in ...:
            for k in ...:
                if something:
                    return
    inner()

Use exceptions

Philosophically, this is what exceptions are for, breaking the program flow through the structured programming building blocks (if, for, while) when necessary.

The advantage is that you don't have to break the single piece of code into multiple parts. This is good if it is some kind of computation that you are designing while writing it in Python. Introducing abstractions at this early point may slow you down.

Bad thing with this approach is that interpreter/compiler authors usually assume that exceptions are exceptional and optimize for them accordingly.

class ContinueI(Exception):
continue_i = ContinueI()
for i in ...:
        for j in ...:
            for k in ...:
                if something:
                    raise continue_i
    except ContinueI:
        continue

Create a special exception class for this, so that you don't risk accidentally silencing some other exception.

Something else entirely

I am sure there are still other solutions.

Can't believe I didn't think of moving my second loop to another method. I'm getting slow – pmccallum Feb 16, 2017 at 23:27 To me, using Exceptions is a good way of achieving this. I agree with @user7610 - "philosophically, this is what exceptions are for". – Renato Byrro Jun 23, 2019 at 20:10 @kontur StopIteration is intended for use in Python iterators (and related constructs: generators and coroutines). Reusing it here would be IMO inappropriate. – user7610 Feb 14, 2021 at 10:21

In other languages you can label the loop and break from the labelled loop. Python Enhancement Proposal (PEP) 3136 suggested adding these to Python but Guido rejected it:

However, I'm rejecting it on the basis that code so complicated to require this feature is very rare. In most cases there are existing work-arounds that produce clean code, for example using 'return'. While I'm sure there are some (rare) real cases where clarity of the code would suffer from a refactoring that makes it possible to use return, this is offset by two issues:

  • The complexity added to the language, permanently. This affects not only all Python implementations, but also every source analysis tool, plus of course all documentation for the language.

  • My expectation that the feature will be abused more than it will be used right, leading to a net decrease in code clarity (measured across all Python code written henceforth). Lazy programmers are everywhere, and before you know it you have an incredible mess on your hands of unintelligible code.

  • So if that's what you were hoping for you're out of luck, but look at one of the other answers as there are good options there.

    Interesting. I agree with Guido here. While it would be nice for some cases it would be abused. Another reason for not implementing it is that right now it is pretty straight forward to port code back and forth between C and Python. Once Python starts picking up features that other languages lack this becomes harder. Take for example the fact that you can have an else statement on a for loop in Python... this makes code less portable to other languages. – eric.frederich Feb 14, 2013 at 17:24 This is more of a red-heiring than a good counter-argument, but it seems to me that the behavior of for-else is more complicated, more difficult to read, and probably more abused (if not an outright mistake) than named loops would be. I think I would have used a different keyword than else - perhaps something like resume would have been good? You break in the loop and the resume is right after it? – ArtOfWarfare Jul 21, 2014 at 17:35 This makes me sad. I can't believe how I love and hate Python at the same time. So beautiful, yet so wtf. – jlh Jul 19, 2017 at 20:21 @jlh Mostly wtf for me. Sometimes I think it wants to be different not for legitimate purpose but just to be different. This is a good example of that. I come across the need to break outer loops quite often. – Rikaelus Sep 24, 2017 at 6:26 1. "I'm too lazy, this is too much work" 2. "Lazy programmers will abuse it" You guys think that's a good argument?!? – Preston Jun 25, 2020 at 16:35 -1: The OP clearly stated that they knew they could do something like this, and this just looks like a messier version of the accepted answer (which predates yours by 8 months, so it couldn't have been that you just missed the accepted answer). – ArtOfWarfare Jul 21, 2014 at 17:31 The accepted answer is not clearer if you've never seen for, else before (and I think even most people who have can't remember off the top of their head how it works). – asmeurer Jul 21, 2014 at 20:08

    We want to find something and then stop the inner iteration. I use a flag system.

    for l in f:
        flag = True
        for e in r:
            if flag==False:continue
            if somecondition:
                do_something()
                flag=False
                    I don't know why your solution was downvoted; someone posted basically exactly the same thing and got upvoted 10 times
    – Locane
                    Dec 5, 2018 at 8:09
                    Maybe because there is basically exactly the same thing posted here already, I guess... And the False:continue thing is... unusual formatting. As it's often the case in "natural" systems where exponential are the norm, you only have to get lucky a few times on SO to amass significant amount of reputation points. Anyways, my "best" answers are usually the least popular ones.
    – user7610
                    Mar 29, 2019 at 10:39
                    @Esther couple of pointers: 1) don't use flag == False; it should be flag is False to test for equality with True or False. Also, in an if statement, you don't need to test equality like this. Just say if not flag:
    – Rob Grant
                    Dec 10, 2021 at 11:06
    

    I think one of the easiest ways to achieve this is to replace "continue" with "break" statement,i.e.

    for ii in range(200):
     for jj in range(200, 400):
        ...block0...
        if something:
            break
     ...block1...       
    

    For example, here is the easy code to see how exactly it goes on:

    for i in range(10):
        print("doing outer loop")
        print("i=",i)
        for p in range(10):
            print("doing inner loop")
            print("p=",p)
            if p==3:
                print("breaking from inner loop")
                break
        print("doing some code in outer loop")
    

    Another way to deal with this kind of problem is to use Exception().

    for ii in range(200):
            for jj in range(200, 400):
                ...block0...
                if something:
                    raise Exception()
        except Exception:
            continue
        ...block1...
    

    For example:

    for n in range(1,4):
        for m in range(1,4):
            print n,'-',m
    

    result:

    Assuming we want to jump to the outer n loop from m loop if m =3:

    for n in range(1,4):
            for m in range(1,4):
                if m == 3:
                    raise Exception()            
                print n,'-',m
        except Exception:
            continue
    

    result:

    Reference link:http://www.programming-idioms.org/idiom/42/continue-outer-loop/1264/python

    I just did something like this. My solution for this was to replace the interior for loop with a list comprehension.

    for ii in range(200):
        done = any([op(ii, jj) for jj in range(200, 400)])
        ...block0...
        if done:
            continue
        ...block1...
    

    where op is some boolean operator acting on a combination of ii and jj. In my case, if any of the operations returned true, I was done.

    This is really not that different from breaking the code out into a function, but I thought that using the "any" operator to do a logical OR on a list of booleans and doing the logic all in one line was interesting. It also avoids the function call.

    The best approach I know to continue an outer loop is using a Boolean that is scoped under the outer loop and breaking the inner one. Although, depending on the use case you may not break the inner loop, continuing an outer loop inside its inner loop implicitly suggests that you want to immediately jump to the first line of the outer loop and avoid any further execution in the inner one. That is why I added a break statement.

    for i in range(0, 6):
        should_continue = False
        for f in range(1, i * 2):
            print(f"f = {f}")
            if (not (f % 1337) or not (f % 7)):
                print(f"{f} can be divided, continue outer loop")
                should_continue = True
                # leaves inner loop
                break
        if(should_continue): continue
        # Outer loop's code goes here
        print(f'Reached outer loop\ni = {i}')
    

    This approach avoids calling any functions and dealing with possible drawbacks. Calling a function is known to be a rather expensive operation, specially for Games. Now imagine a deeply nested for loop that will run millions of times, wrapping it inside a function won't result in a smooth experience.

    Wrapping the loop inside an exception block is also a bad idea and will be way slower than functions. This is because Python needs a lot of overhead to trigger the exceptions mechanism and later restore the runtime state, exceptions are designed to be used exceptionally. Taking that in mind, even some CPU optimizations such as speculative execution should not be applied to exception blocks and probably aren't.

    The only "problem" I found in this approach is that break will jump once outside of the inner loop, landing on continue, which, in turn, will jump one more time. This, as opposed to a goto statement in C or JavaScript, is a bit more clumsy, but doesn't have any visible impact in performance, because it would generate only one extra instruction that runs as fast as your CPU's clock or as the interpreter implementation.