How to break out of multiple loops?

后端 未结 30 3333
情书的邮戳
情书的邮戳 2020-11-21 05:48

Given the following code (that doesn\'t work):

while True:
    #snip: print out current state
    while True:
        ok = get_input(\"Is this ok? (y/n)\")
          


        
相关标签:
30条回答
  • 2020-11-21 06:21

    First, you may also consider making the process of getting and validating the input a function; within that function, you can just return the value if its correct, and keep spinning in the while loop if not. This essentially obviates the problem you solved, and can usually be applied in the more general case (breaking out of multiple loops). If you absolutely must keep this structure in your code, and really don't want to deal with bookkeeping booleans...

    You may also use goto in the following way (using an April Fools module from here):

    #import the stuff
    from goto import goto, label
    
    while True:
        #snip: print out current state
        while True:
            ok = get_input("Is this ok? (y/n)")
            if ok == "y" or ok == "Y": goto .breakall
            if ok == "n" or ok == "N": break
        #do more processing with menus and stuff
    label .breakall
    

    I know, I know, "thou shalt not use goto" and all that, but it works well in strange cases like this.

    0 讨论(0)
  • 2020-11-21 06:21

    There is no way to do this from a language level. Some languages have a goto others have a break that takes an argument, python does not.

    The best options are:

    1. Set a flag which is checked by the outer loop, or set the outer loops condition.

    2. Put the loop in a function and use return to break out of all the loops at once.

    3. Reformulate your logic.

    Credit goes to Vivek Nagarajan, Programmer since 1987


    Using Function

    def doMywork(data):
        for i in data:
           for e in i:
             return 
    

    Using flag

    is_break = False
    for i in data:
       if is_break:
          break # outer loop break
       for e in i:
          is_break = True
          break # inner loop break
    
    0 讨论(0)
  • 2020-11-21 06:23

    I tend to agree that refactoring into a function is usually the best approach for this sort of situation, but for when you really need to break out of nested loops, here's an interesting variant of the exception-raising approach that @S.Lott described. It uses Python's with statement to make the exception raising look a bit nicer. Define a new context manager (you only have to do this once) with:

    from contextlib import contextmanager
    @contextmanager
    def nested_break():
        class NestedBreakException(Exception):
            pass
        try:
            yield NestedBreakException
        except NestedBreakException:
            pass
    

    Now you can use this context manager as follows:

    with nested_break() as mylabel:
        while True:
            print "current state"
            while True:
                ok = raw_input("Is this ok? (y/n)")
                if ok == "y" or ok == "Y": raise mylabel
                if ok == "n" or ok == "N": break
            print "more processing"
    

    Advantages: (1) it's slightly cleaner (no explicit try-except block), and (2) you get a custom-built Exception subclass for each use of nested_break; no need to declare your own Exception subclass each time.

    0 讨论(0)
  • 2020-11-21 06:23

    probably little trick like below will do if not prefer to refactorial into function

    added 1 break_level variable to control the while loop condition

    break_level = 0
    # while break_level < 3: # if we have another level of nested loop here
    while break_level < 2:
        #snip: print out current state
        while break_level < 1:
            ok = get_input("Is this ok? (y/n)")
            if ok == "y" or ok == "Y": break_level = 2 # break 2 level
            if ok == "n" or ok == "N": break_level = 1 # break 1 level
    
    0 讨论(0)
  • 2020-11-21 06:23

    Here's an implementation that seems to work:

    break_ = False
    for i in range(10):
        if break_:
            break
        for j in range(10):
            if j == 3:
                break_ = True
                break
            else:
                print(i, j)
    

    The only draw back is that you have to define break_ before the loops.

    0 讨论(0)
  • 2020-11-21 06:23

    Similar like the one before, but more compact. (Booleans are just numbers)

    breaker = False #our mighty loop exiter!
    while True:
        while True:
            ok = get_input("Is this ok? (y/n)")
            breaker+= (ok.lower() == "y")
            break
    
        if breaker: # the interesting part!
            break   # <--- !
    
    0 讨论(0)
提交回复
热议问题