Embercode
✕
LoopsLesson 4 of 16

45 min read

Break and continue in Python loops

Why this matters

A loop does not always need to run to the end. You stop searching a list once you have found the item. You skip a record that is broken and keep going with the rest. You give up on a grid once you find the first cell that breaks a rule. Without ways to change the normal flow of a loop, every one of these cases would need extra flags and awkward conditions, and the code would be hard to read.

Python gives you two statements for this: break and continue. It does not have labels, so leaving two loops at once needs a flag variable or a function with return. These tools are short, and they are easy to misuse. This lesson shows what each one really does, with exact traces, and then shows the two-pointer pattern, one of the most useful early-exit methods in interviews.

The idea from first principles

Normally a loop follows one fixed path. The check runs, the body runs from top to bottom, the update runs, and the check runs again. A change to that path needs a new kind of jump. The program has to be told: leave the loop now, or skip to the next pass.

break is the first kind. It jumps to the line just after the loop, and the loop's check is not made again. continue is the second kind. It jumps to the end of the body. In a for loop, that means the next value is taken. In a while loop, it means the check at the top runs again. Both statements apply only to the nearest loop that contains them. If you are not careful about which loop is nearest, you will change the wrong one.

An everyday analogy: searching a shelf

Imagine you are searching a shelf of books for one title. You take each book in turn. When you find the title, you stop. There is no point looking at the remaining books, so you leave the shelf right away. That is break.

Now imagine you are reading the shelf to count the books that are in good condition. A damaged book is not counted, so you put it aside and move to the next one. You still look at every book, but you skip the counting step for the damaged ones. That is continue.

Worked example 1: stopping at the first negative value

The first program reads a list of numbers and reports the position of the first negative value. Once that position is found, nothing else matters, so break is the right tool.

range(n) gives the numbers 0, 1, up to n - 1, so a for loop over range(n) runs n times. The program reads the count first, then one number per line.

n = int(input())
first_negative = -1
for i in range(n):
    value = int(input())
    if value < 0:
        first_negative = i
        break
if first_negative == -1:
    print("No negative value")
else:
    print(f"First negative at index {first_negative}")

Input, one value per line:

5
4
7
9
-3
2

The output is:

First negative at index 3

Trace the loop. The indexes are 0 to 4. The value 4 is not negative. The value 7 is not negative. The value 9 is not negative. The value -3 is negative, so first_negative becomes 3 and break ends the loop. The value 2 is never read.

That last point matters. After break, the loop does not call input() again. The line with the 2 is still waiting in the input. In a longer program, a later input() would get that line. Keep this in mind whenever a break skips input.

The sentinel value -1 for "not found" is a common choice. It works here because index numbers are never negative. Use a sentinel only when it cannot be a valid answer.

Worked example 2: skipping values with continue

Now take the opposite problem. You want the sum of the positive values only, and you want to read all of them. A negative value should be skipped, not stop the loop. The continue statement does that. When continue runs, the rest of the body is skipped for this pass, and the for loop moves on to the next value.

Input, one value per line:

5
3
-2
5
-1
4
n = int(input())
total = 0
skipped = 0
for i in range(n):
    value = int(input())
    if value < 0:
        skipped += 1
        continue
    total += value
print(f"Sum of positives: {total}")
print(f"Skipped: {skipped}")

The output is:

Sum of positives: 12
Skipped: 2

Trace the passes. The values are 3, -2, 5, -1 and 4. The value 3 is added, making 3. The value -2 is skipped, so skipped becomes 1 and the line total += value does not run. The value 5 is added, making 8. The value -1 is skipped, so skipped becomes 2. The value 4 is added, making 12.

The key point is that continue did not stop the loop. It stopped one pass. Every value was read, and the loop ran five times.

Notice where the counting happens. The counter skipped goes up before continue, because the skip itself is the event you want to count. If you put the counter after continue, it would never run.

The continue trap in a while loop

continue works differently in a while loop, and this is the most dangerous difference in this lesson. In a for loop, the next value is taken, so the loop always moves on. In a while loop, the loop moves only if the code moves it. If the update is at the bottom of the body, continue skips it, and the loop can run forever.

Here is a loop that counts from 0 to 4 and skips the value 2:

i = 0
while i < 5:
    if i == 2:
        continue
    print(i)
    i += 1

The program prints 0 and 1, then it prints nothing more. When i is 2, the if runs continue, which jumps to the check i < 5. That check is still true, so the body runs again. i never changes, so the same continue runs again. The program keeps running until you stop it, for example with Ctrl+C.

The fix is to change i before the continue, or to use a for loop, where the next value is taken for you:

Python · editable

This version prints 0, 1, 3 and 4. The rule for while loops is easy to remember: before you use continue, check that the variable changes before the continue line.

The same trap is possible in the while True pattern from the previous lesson. There, continue jumps to the top of the body and skips the check at the bottom. Check that the code before the continue still sets the values the loop depends on.

Worked example 3: stopping at a sentinel with while True

Sometimes the end of a loop is decided deep inside the body, not by the loop's check. A common shape is the loop that runs forever and leaves through break when a special value appears. That shape is written while True. The check is always true, so the only way out is break.

The next program reads numbers until it sees 0, then prints their total. Input, one value per line: 4, 7, 9, 0.

total = 0
count = 0
while True:
    value = int(input())
    if value == 0:
        break
    total += value
    count += 1
print(f"Count: {count}")
print(f"Total: {total}")

The output is:

Count: 3
Total: 20

The while True loop looks strange at first, because it seems to never stop. The break inside the body is the exit. Use this shape when the stop check needs to read a value first, and the value cannot be checked in the loop's first line. This is the same pattern as the menu in the previous lesson.

Keep the exit near the value it tests, so the reader does not have to hunt for it. A short loop with one clear exit is good style.

Leaving nested loops without labels

A plain break leaves only the nearest loop. When you have two loops and want to leave both, a plain break is not enough. Some languages let you put a name on a loop, so that break can point to it. Python does not have this feature.

Python gives you two ways to get the same result. The first is a flag, which is a variable that records a fact, such as "found". The outer loop checks the flag after the inner loop ends. The second is a function with return. A return leaves the whole function at once, so it leaves every loop inside it.

The next program searches a list for two values that add up to a target. It uses a flag. Input: the list on one line, 2 7 11 15 9, then the target 9 on the next line.

numbers = [int(x) for x in input().split()]
target = int(input())
index_i = -1
index_j = -1
found = False
for i in range(len(numbers)):
    for j in range(i + 1, len(numbers)):
        if numbers[i] + numbers[j] == target:
            index_i = i
            index_j = j
            found = True
            break
    if found:
        break
if found:
    print(f"Pair at positions {index_i} and {index_j}")
else:
    print("No pair")

The output is:

Pair at positions 0 and 1

Read the new line first. input().split() splits the line at the spaces and returns a list of text values. int(x) turns each text value into a number, and the square brackets build the list. This is a list comprehension, which builds a list in one line.

Trace the search. The outer loop starts with i at 0. The inner loop starts at j = 1: 2 + 7 is 9, which matches the target. The program saves the positions and sets the flag. The inner break ends the inner loop. Then if found: break ends the outer loop. Without that second check, the outer loop would keep going and could overwrite the answer.

Notice that the inner loop starts at i + 1. Starting from i would pair a value with itself, which is not allowed in this problem. It would also count each pair twice, once in each order. Starting at i + 1 is one of the most common choices in pair problems, and interviewers check that you know why.

The same search with a function is shorter. The return leaves both loops at once, so no flag is needed:

def find_pair(numbers, target):
    for i in range(len(numbers)):
        for j in range(i + 1, len(numbers)):
            if numbers[i] + numbers[j] == target:
                return i, j
    return None
 
 
numbers = [int(x) for x in input().split()]
target = int(input())
pair = find_pair(numbers, target)
if pair is None:
    print("No pair")
else:
    print(f"Pair at positions {pair[0]} and {pair[1]}")

The output for the same input is Pair at positions 0 and 1. The function returns None when no pair exists. None is Python's value for "no value", and is None checks for it.

Worked example 4: two pointers on a sorted list

The two-pointer pattern is a loop that moves two indexes at the same time, usually one from each end of a sorted list. It is a standard interview technique, and it uses early exit as the way to stop when the answer is found.

Here is the problem. You have a sorted list and a target. Find two values that add up to the target. A brute force solution checks every pair, which takes time proportional to n times n. The two-pointer method takes time proportional to n, because each step moves one pointer and the pointers never go back.

The method is this. Put lo at the first index and hi at the last. Look at the sum of the two values. If the sum is too small, move lo right to get a bigger value. If the sum is too big, move hi left to get a smaller value. If the sum is exactly right, you are done. Stop when the pointers meet.

The program below reads a sorted list and a target, then prints the 1-based positions of the first pair found. The positions start at 1 in the output, but the list indexes start at 0, so the program adds 1 when it prints. Input: the list 1 3 4 6 8 11 on one line, then the target 12.

numbers = [int(x) for x in input().split()]
target = int(input())
lo = 0
hi = len(numbers) - 1
found = False
while lo < hi:
    total = numbers[lo] + numbers[hi]
    if total == target:
        found = True
        break
    elif total < target:
        lo += 1
    else:
        hi -= 1
if found:
    print(f"Pair: {lo + 1} {hi + 1}")
else:
    print("No pair")

The output is:

Pair: 1 6

Trace the first step. The pointers start at 0 and 5, the values 1 and 11. The sum is 12, which equals the target, so the search stops at once and reports positions 1 and 6. The answer is found on the first step because the first pair happens to match.

Now change the target to 10. The table below traces each step. Each row is one pass, and the values come from the list indexes lo and hi.

PasslohiValuesSumWhat happens
1051 and 1112too big, so hi moves left
2041 and 89too small, so lo moves right
3143 and 811too big, so hi moves left
4133 and 69too small, so lo moves right
5234 and 610match, so the loop stops

The program prints Pair: 3 4, because the pointers stand on indexes 2 and 3, and 1 is added to each.

The reason the method works is that a pointer moves only when it cannot be part of a pair with the other pointer's value. If the sum is too big, the right value is too big for every left value that is at least lo, so it can be dropped. That is the key argument, and it is the answer you give an interviewer when asked to prove correctness.

What happens inside: how break and continue jump

The standard Python program, called CPython, turns a loop into bytecode, which is a list of small instructions for the Python interpreter. break and continue become jumps to other instructions, as in most languages. A jump moves the program to a different line of instructions without running the lines between.

The cost of break and continue is almost nothing. They do not make the program slower in any practical way. Their cost is in readability. A reader who sees a continue must think about where the loop goes next, and a reader who sees a flag must follow it to the place where it is set. Use these tools when they make the code clearer, and avoid them when a simple condition would do.

Worked example 5: skipping duplicates in a sorted list

Sometimes continue is the cleanest way to say "ignore this value and move on". Here the list is sorted, so equal values sit next to each other. A value is a duplicate when it equals the value just before it. The program prints each distinct value once, and uses continue to skip the duplicates.

Input: 1 1 2 2 2 5 9 on one line.

numbers = [int(x) for x in input().split()]
printed = 0
for i in range(len(numbers)):
    if i > 0 and numbers[i] == numbers[i - 1]:
        continue
    print(numbers[i], end=" ")
    printed += 1
print()
print(f"Distinct: {printed}")

The output is:

1 2 5 9 
Distinct: 4

The end=" " part of print replaces the usual line break with a space, so the values stay on one line. The plain print() on the next line ends that line.

Trace the passes. Index 0 holds 1, and there is no earlier value, so i > 0 is false and the value is printed. Index 1 holds 1, which equals index 0, so continue skips the print and the count. Index 2 holds 2, which is different, so it is printed. Indexes 3 and 4 also hold 2, equal to the value before them, so both are skipped. Index 5 holds 5 and is printed, and index 6 holds 9 and is printed. The count is 4.

The check i > 0 comes first on purpose. At index 0 there is no value before it, and numbers[i - 1] would be numbers[-1]. In Python, a negative index counts from the end of the list, so numbers[-1] is the last value. Python does not raise an error for this, so the check does not protect the program from a crash. It protects the answer. The and operator stops checking as soon as the first part is false, so numbers[i - 1] is never read when i is 0.

To see why the check matters, remove it. Input: 5 5 on one line.

numbers = [int(x) for x in input().split()]
printed = 0
for i in range(len(numbers)):
    if numbers[i] == numbers[i - 1]:
        continue
    print(numbers[i], end=" ")
    printed += 1
print()
print(f"Distinct: {printed}")

The output is:

 
Distinct: 0

At index 0, numbers[-1] is the last 5, which equals the first 5. The first value is skipped, and so is the second. The output shows an empty line and Distinct: 0, with no error to warn you.

Worked example 6: labeled continue, written with a flag

Some languages let you write continue with a loop name, which skips the rest of the named loop's current pass from inside a nested loop. Python has no such form, so the same effect needs a flag.

This example prints the products in a 3 by 3 table. It skips the rest of a row as soon as a product equals 4. The example needs no input, so you can run it.

Python · editable

The output is:

1 2 3 
2 3 6 9 

Look closely at the second line. When row 2 reaches column 2, the product is 4. The inner break ends the inner loop, and the flag is set. The if skip_rest: continue line then moves the outer loop to row 3, and that skips the print() at the end of row 2. So row 2 never gets its own line, and row 3 prints its values after the 2 that row 2 printed before the break. This is a real trap. Any output that comes after the inner loop is lost when the outer loop skips to its next pass. If you need one line per row even after a skip, put the line-ending call in a place that always runs.

A flag or a break

Many programs use a flag instead of break. The two styles often solve the same problem, and you should know both, because you will read both in real code.

This program searches a list for a target value in two ways. The first uses a flag in the loop's check. The second uses break. Both print the index 2. The program also shows the list method index.

Python · editable

The output is:

2
2
2

In the flag version, the loop's check is i < n and not found, so the loop stops after the pass that sets the flag. The i += 1 line still runs on that pass, because it is after the if. For a counter with no other effects, that difference does not matter.

In the break version, the loop ends at once. It is shorter, and it has one less variable to keep right.

Both versions give the same answer, so the choice is about clarity. The flag version is clear when several conditions decide when to stop, because each one can be part of the check. The break version is clear when the stop happens at one place in the body.

Python lists also have an index method, which does the search for you. It returns the position of the first match. If the value is not in the list, it raises ValueError. Use the method when a plain search is all you need.

Inside a function, a return is a third choice. It gives the answer at once and leaves every loop, so it is often the clearest of the three.

Worst case and average case for early exit

Early exit makes a loop faster on some inputs, but it does not change the worst case. Interviewers usually ask for the worst case, because it is the guarantee you can promise. The average case tells you what to expect in practice.

For the search that stops at the first negative, the worst case is a list with no negatives. Then every value is checked, and the time is O(n). The best case is a negative at the first position, which takes one check. The average depends on how the negatives are spread out. You should state the worst case first, then mention the best and average cases when they matter.

For the two-pointer search on a sorted list, each step moves one pointer, and the pointers never go back. The loop does at most n steps in total, so the time is O(n) in the worst case, and the early exit only helps when the pair is found soon. In the worst case, the pair is at the very end, or there is no pair at all, and the loop still scans the whole list.

For the nested search with two loops, the worst case is no pair at all. The inner loop then runs for every pair, which is about n times n divided by 2 checks, so the time is O(n squared). The early exit reduces the work only when a pair exists near the start.

When an interviewer asks whether an early exit makes the solution faster, answer with both cases. Say "in the worst case it still checks every item, so the time stays O(n), but on many inputs it stops sooner." That answer is accurate and it shows you understand the difference.

Common mistakes

Breaking the wrong loop

A break inside an inner loop ends only the inner loop. If you meant to stop the whole search, you need a flag or a function with return. Here is a common error:

Python · editable

The output is:

00 01 02 10 11 20 

The break stops the inner loop only. The outer loop keeps going, so the search does not stop when the first answer is found. The line print() runs once at the end, which is why the output is one line.

Using a label

Python does not accept labels, so a program that uses one fails to run:

for i in range(3):
    for j in range(3):
        if i == j:
            break outer

The error is:

  File "/path/to/main.py", line 4
    break outer
          ^^^^^
SyntaxError: invalid syntax

The caret points at the word outer. Python does not know the name, so it stops reading there. Use a flag or a function with return instead.

A break inside a match statement

Python has a match statement, which chooses between cases. A break inside a match case still ends the loop around it, not only the match. This program shows it:

Python · editable

The output is:

value 1
after loop

The value 3 is never reached, because the break for 2 ends the for loop.

Forgetting the update before continue in a while loop

This is the trap described above. The fix is to move the change of the variable above the continue, or to write the loop as a for.

Code after break or continue

Code placed directly after break or continue in the same block can never run. Python does not report this as an error. The line is skipped and never runs. Some checking tools warn about it.

Python · editable

The output is:

after loop

Using continue to skip the work you need

A continue that skips the update of a counter can make the counter wrong. Suppose you count how many values are kept, and you use continue for values you do not want. The count is right only if the increment happens after the continue line, not before it. Check the order of statements around every continue.

Debugging walkthrough: a search that finds no pair

A learner wrote the two-pointer program from worked example 4, but swapped the two branches. When the sum is too big, the code moves lo right. When the sum is too small, the code moves hi left. The learner expected Pair: 3 4 for the list 1, 3, 4, 6, 8, 11 and target 10. The program prints No pair. The loop below prints each pass to show what it does:

Python · editable

The output is:

lo=0 hi=5 sum=12
lo=1 hi=5 sum=14
lo=2 hi=5 sum=15
lo=3 hi=5 sum=17
lo=4 hi=5 sum=19
No pair

Step 1: list the expected behaviour. For this list and target 10, the expected pair is 4 and 6, at indexes 2 and 3.

Step 2: trace the pointers in the output. The first sum is 12, which is too big. The code moves lo right, so the sum gets bigger, not smaller. Every later line shows lo moving up while hi stays at 5. The pointers meet and the loop ends with no match.

Step 3: compare the branch with the rule. A sum that is too big needs hi to move left. The code does the opposite.

Step 4: fix the code by swapping the two branches back, so that hi -= 1 runs when the sum is too big and lo += 1 runs when it is too small. The corrected program is the one in worked example 4.

Step 5: test the fix. Run the case with target 10, which prints Pair: 3 4, and a case where no pair exists, such as target 100, which prints No pair.

The lesson is the same as before. Write the expected trace by hand, then compare each step with the code. A swapped branch is one of the most common bugs in two-pointer code, and a print line inside the loop shows the bug quickly.

Edge cases to check

Early exit makes edge cases easier to get wrong, because some passes never happen. Check these:

An empty list. len(numbers) - 1 is -1, so the check lo < hi is false from the start. The loop does not run, and the program prints No pair.

A list with one value. The two pointers start on the same index, so lo < hi is false. The pair needs two different positions, so No pair is correct.

A list with two equal values. For the list 5 5 and target 10, the pointers start at indexes 0 and 1. The sum is 10, so the program prints Pair: 1 2. The two-pointer method finds two equal values, because they sit at different positions.

A target that is the sum of the first and last values. The first sum is checked before any pointer moves, so the answer is found right away.

A target that is too small or too large for every pair. The pointers keep moving until they meet, then the loop ends, and the program prints No pair.

Interview patterns

Early exit appears in many interview questions. Learn the patterns below, because they cover most of the problems you will meet.

The first is the search with early exit. Look through a list until you find a match, then stop. The time depends on where the match is. In the worst case, you look at every item, so the time is O(n). The average case can be faster, but interviewers usually ask about the worst case.

The second is the two-pointer sweep on sorted data. Move one pointer from each end, or both from one end, and never move back. Each pointer moves at most n times, so the total time is O(n). The method needs sorted data or a rule that tells you which pointer to move.

The third is the search across a grid. You look for the first cell that matches a rule, and you stop both loops when you find it, with a flag or a function. The time is the number of cells you check, which is O(rows times columns) in the worst case.

When you explain your answer, say three things: what you return, why an early exit is safe, and the worst-case time. For the two-pointer pair search, you say: the answer is the first matching pair, the pointer that moves is the one that cannot make a match, and the time is O(n).

Real-world uses

Early exit is everywhere. A spell checker stops once it finds a word that is not in the dictionary, if the rule is to report the first error. A form checker stops at the first invalid field when it only needs to show one error. A file reader stops when it reaches the end marker in a file. A route planner stops searching once it reaches the destination. A search engine stops ranking a document once the score is good enough for the top results.

The two-pointer pattern is used in merging sorted lists, in checking whether a string is a palindrome, and in finding ranges that meet a condition. You will see it again in the complexity and arrays modules.

Practice

Try each exercise before you open the answer. Trace at least one of them on paper before you run it.

  1. Read integers until the value 0 appears. Print the largest value read before the 0. Use break when you see 0. If no value comes before the 0, print None.

Show the answer

largest = None
while True:
    value = int(input())
    if value == 0:
        break
    if largest is None or value > largest:
        largest = value
print(largest)
  1. Read 6 integers and print their sum, skipping any value that is greater than 100. Use continue.

Show the answer

total = 0
for _ in range(6):
    value = int(input())
    if value > 100:
        continue
    total += value
print(total)

The name _ marks a value that the loop does not use.

  1. Print the numbers from 1 to 20 that are multiples of 3, using continue for the others. Then rewrite the same output without continue, and say which version you prefer and why.

Show the answer

for i in range(1, 21):
    if i % 3 != 0:
        continue
    print(i)
 
for i in range(3, 21, 3):
    print(i)

The second version is shorter and easier to read. range takes a third number, the step, so range(3, 21, 3) gives 3, 6, 9 and so on up to 18.

  1. Print the first pair (i, j) with i less than j, both from 1 to 5, whose product is 12. Python has no labels, so use a function with return.

Show the answer

def first_pair():
    for i in range(1, 6):
        for j in range(i + 1, 6):
            if i * j == 12:
                return i, j
    return None
 
print(first_pair())

The output is (3, 4).

  1. Read a list of numbers on one line and print YES if any value appears twice. Stop as soon as a duplicate is found. Python has no labels, so use a flag.

Show the answer

numbers = [int(x) for x in input().split()]
duplicate = False
for i in range(len(numbers)):
    for j in range(i + 1, len(numbers)):
        if numbers[i] == numbers[j]:
            duplicate = True
            break
    if duplicate:
        break
print("YES" if duplicate else "NO")

For the input 3 1 4 1, the output is YES.

  1. Rewrite the while loop that skips 2 so it does not hang. Keep the output the same.

Show the answer

i = 0
while i < 5:
    i += 1
    if i == 3:
        continue
    print(i - 1)

The output is 0, 1, 3 and 4. The update i += 1 now comes before the continue, so the loop always moves on.

  1. Explain the difference between break and continue in one sentence each, using the shelf analogy.

  2. Use the two-pointer method on a sorted list to count how many pairs add up to a target, not just whether one exists. Test with the list 1 2 3 4 and target 5, where the answer is 2.

Show the answer

numbers = [int(x) for x in input().split()]
target = int(input())
lo = 0
hi = len(numbers) - 1
count = 0
while lo < hi:
    total = numbers[lo] + numbers[hi]
    if total == target:
        count += 1
        lo += 1
        hi -= 1
    elif total < target:
        lo += 1
    else:
        hi -= 1
print(count)
  1. Write a program that reads a 3 by 3 grid of numbers, one row per line, and prints the position of the first cell whose value is 0 as a pair (row, column), counting from 0. Use a flag to leave both loops.

Show the answer

grid = [[int(x) for x in input().split()] for _ in range(3)]
found = None
for r in range(3):
    for c in range(3):
        if grid[r][c] == 0:
            found = (r, c)
            break
    if found is not None:
        break
print(found)

For the rows 1 2 3, 4 0 6, 0 8 9, the output is (1, 1).

  1. Explain why the two-pointer method on a sorted list cannot pair a value with itself.

Show the answer

The pointers start at different indexes, and they only move toward each other. A pointer that moves never goes back, so the two pointers never stand on the same index at the same time. Each value is used at most once in a pair.

What you now know

  • break leaves the nearest loop at once. Use it when the answer is found or the loop has no more work.
  • continue skips the rest of one pass. In a for loop, the next value is taken. In a while loop, check that the variable changes before continue, or the loop can run forever.
  • Python has no labels. Leave nested loops with a flag, or with a function and return.
  • while True with a break is a clean shape when the stop check depends on a value read inside the body.
  • The two-pointer method uses early exit on sorted data and runs in O(n) time.
  • After a break, the remaining input is not read, which can matter for later reads.

The next lesson puts loops inside loops. You will count the work they do, sort a list with nested loops, and solve the classic problems interviewers ask.

Practice this topic: coding problems for Loops →

Stuck? Ask the tutor

Ask about anything in this lesson. Answers are short and use simple words.

Sign in to ask the tutor.

← The do-while pattern in Python