Controlling Loops Using break and continue

As a rule, for and while loops execute all the statements in their body on each iteration. However, sometimes it is handy to be able to break that rule. Python provides two ways of controlling the iteration of a loop: break, which terminates execution of the loop immediately, and continue, which skips ahead to the next iteration.

The break Statement

In Repetition Based on User Input, we showed a program that continually read input from a user until the user typed quit. Here is a program that accomplishes the same task, but this one uses break to terminate execution of the loop when the user types quit:

 while​ True:
  text = input(​"Please enter a chemical formula (or 'quit' to exit): "​)
 if​ text == ​"quit"​:
 print​(​"…exiting program"​)
 break
 elif​ text == ​"H2O"​:
 print​(​"Water"​)
 elif​ text == ​"NH3"​:
 print​(​"Ammonia"​)
 elif​ text == ​"CH4"​:
 print​(​"Methane"​)
 else​:
 print​(​"Unknown compound"​)

The loop condition is strange: it evaluates to True, so this looks like an infinite loop. However, when the user types quit, the first condition, text == "quit", evaluates to True. The print("…exiting program") statement is executed, and then the break statement, which causes the loop to terminate.

As a style point, we are somewhat allergic to loops that are written like this. We find that a loop with an explicit condition is easier to understand.

Sometimes a loop’s task is finished before its final iteration. Using what you have seen so far, though, the loop still has to finish iterating. For example, let’s write some code to find the index of the first digit in string ’C3H7’. The digit 3 is at index 1 in this string. Using a for loop, we would have to write something like this:

 >>>​​ ​​s​​ ​​=​​ ​​'C3H7'
 >>>​​ ​​digit_index​​ ​​=​​ ​​-1​​ # This will be -1 until we find a digit.
 >>>​​ ​​for​​ ​​i​​ ​​in​​ ​​range(len(s)):
 ...​​ # If we haven't found a digit, and s[i] is a digit
 ...​​ ​​if​​ ​​digit_index​​ ​​==​​ ​​-1​​ ​​and​​ ​​s[i].isdigit():
 ...​​ ​​digit_index​​ ​​=​​ ​​i
 ...
 >>>​​ ​​digit_index
 1

Here we use variable digit_index to represent the index of the first digit in the string. It initially refers to -1, but when a digit is found, the digit’s index, i, is assigned to digit_index. If the string doesn’t contain any digits, then digit_index remains -1 throughout execution of the loop.

Once digit_index has been assigned a value, it is never again equal to -1, so the if condition will not evaluate to True. Even though the job of the loop is done, the loop continues to iterate until the end of the string is reached.

To fix this, you can terminate the loop early using a break statement, which jumps out of the loop body immediately:

 >>>​​ ​​s​​ ​​=​​ ​​'C3H7'
 >>>​​ ​​digit_index​​ ​​=​​ ​​-1​​ # This will be -1 until we find a digit.
 >>>​​ ​​for​​ ​​i​​ ​​in​​ ​​range(len(s)):
 ...​​ # If we find a digit
 ...​​ ​​if​​ ​​s[i].isdigit():
 ...​​ ​​digit_index​​ ​​=​​ ​​i
 ...​​ ​​break​​ # This exits the loop.
 ...
 >>>​​ ​​digit_index
 1

Notice that because the loop terminates early, we were able to simplify the if statement condition. As soon as digit_index is assigned a new value, the loop terminates, so it isn’t necessary to check whether digit_index refers to -1. That check existed only to prevent digit_index from being assigned the index of a subsequent digit in the string.

Here’s a flowchart for this code:

images/loop/break.png

One more thing about break: it terminates only the innermost loop in which it’s contained. This means that in a nested loop, a break statement inside the inner loop will terminate only the inner loop, not both loops.

The continue Statement

Another way to bend the rules for iteration is to use the continue statement, which causes Python to skip immediately ahead to the next iteration of a loop. Here, we add up all the digits in a string, and we also count how many digits there are. Whenever a nondigit is encountered, we use continue to skip the rest of the loop body and go back to the top of the loop in order to start the next iteration.

 >>>​​ ​​s​​ ​​=​​ ​​'C3H7'
 >>>​​ ​​total​​ ​​=​​ ​​0​​ # The sum of the digits seen so far.
 >>>​​ ​​count​​ ​​=​​ ​​0​​ # The number of digits seen so far.
 >>>​​ ​​for​​ ​​i​​ ​​in​​ ​​range(len(s)):
 ...​​ ​​if​​ ​​s[i].isalpha():
 ...​​ ​​continue
 ...​​ ​​total​​ ​​=​​ ​​total​​ ​​+​​ ​​int(s[i])
 ...​​ ​​count​​ ​​=​​ ​​count​​ ​​+​​ ​​1
 ...
 >>>​​ ​​total
 10
 >>>​​ ​​count
 2

When continue is executed, it immediately begins the next iteration of the loop. All statements in the loop body that appear after it are skipped, so we execute the assignments to total and count only when s[i] isn’t a letter. Here’s a flowchart for this code:

images/loop/continue.png

Using continue is one way to skip alphabetic characters, but this can also be accomplished by using if statements. In the previous code, continue prevents the variables from being modified; in other words, if the character isn’t alphabetic, it should be processed.

The form of the previous sentence matches that of an if statement, and the updated code is as follows:

 >>>​​ ​​s​​ ​​=​​ ​​'C3H7'
 >>>​​ ​​total​​ ​​=​​ ​​0
 >>>​​ ​​count​​ ​​=​​ ​​0
 >>>​​ ​​for​​ ​​i​​ ​​in​​ ​​range(len(s)):
 ...​​ ​​if​​ ​​not​​ ​​s[i].isalpha():
 ...​​ ​​total​​ ​​=​​ ​​total​​ ​​+​​ ​​int(s[i])
 ...​​ ​​count​​ ​​=​​ ​​count​​ ​​+​​ ​​1
 ...
 >>>​​ ​​total
 10
 >>>​​ ​​count
 2

This new version is easier to read than the first one. Most of the time, it is better to rewrite the code to avoid continue; almost always, the code ends up being more readable.

A Warning About break and continue

break and continue have their place, but they should be used sparingly since they can make programs harder to understand. When people see while and for loops in programs, their first assumption is that the whole body will be executed every time—in other words, that the body can be treated as a single “super statement” when trying to understand the program. If the loop contains break or continue, though, that assumption is false. Sometimes only part of the statement body will be executed, which means the reader has to keep two scenarios in mind.

There are always alternatives: well-chosen loop conditions (as in Repetition Based on User Input) can replace break, and if statements can be used to skip statements instead of continue. It is up to the programmer to decide which option makes the program clearer and which makes it more complicated. As we said in Describing Code, programs are written for human beings; taking a few moments to make your code as clear as possible, or to make clarity a habit, will pay dividends for the lifetime of the program.

Now that code is getting pretty complicated, it’s even more important to write comments describing the purpose of each tricky block of statements.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.59.192