continue in Python: skipping to the next iteration

In Python, continue drops the current loop turn and moves straight to the next one: the rest of the block is skipped, but the walk carries on.
6 min read
Believemy logo

Definition

Inside a loop, not every item deserves the same treatment. A data file holds blank lines and comments, a mailing list holds invalid addresses. So there has to be a way of saying, right in the middle of the walk: leave that one aside, look at the next.

continue is exactly that sentence, boiled down to a single word. The moment Python meets it, it drops the current turn: everything sitting below it in the block simply does not run for that item.

What it does not interrupt, on the other hand, is the loop. The next turn starts as if nothing had happened, with the following item. That is the whole difference with break, which ends the walk for good.

The most common example is reading a file line by line, where two categories are ruled out before the real work begins.

PYTHON
for line in handle:
    if not line.strip():
        continue          # blank line: nothing to handle
    if line.startswith("#"):
        continue          # comment: nothing to handle either
    process(line)

The two if act as doormen. Each one turns away the items it does not want, and process only ever sees lines that cleared both checks. The useful body of the loop fits on a single line, right at the bottom, with no condition wrapped around it.


Why it flattens the code

The objection comes straight away: the same thing can be written with nested conditions and no special keyword. True, and the result is strictly identical.

PYTHON
# The same filter, without continue
for line in handle:
    if line.strip():
        if not line.startswith("#"):
            process(line)

With two filters the nesting stays bearable. The trouble starts when a third and then a fourth criterion turn up six months later: the useful code sits sixteen spaces from the margin, and the condition that led there has scrolled off the top of the screen. Reading one line then means scrolling back and holding in mind everything that is true at that point.

The continue version asks for none of that effort. Each filter is a short self-contained sentence, readable on its own, and the only thing left to know by the bottom of the loop is that every awkward case has already gone. Adding a criterion means inserting two lines, removing one means deleting two.

The pattern has a name, the guard clause, and it is not limited to loops: inside a function, an early return plays exactly the same role for the body that follows.


The two moments it surprises you

The first involves the while loop, and the reason is worth understanding rather than memorising as a rule. With for, the loop moves from one item to the next on its own, so skipping the end of the block never stops it from progressing. With while, progress is the job of the code you write, usually a counter increment. If that increment sits after the continue, it is never reached.

PYTHON
# Infinite loop: i never grows while the condition holds
i = 0
while i < 10:
    if i % 2 == 0:
        continue      # back to the test with the same i, forever
    i += 1
Warning

The program does not crash and prints nothing: it spins, and it has to be stopped by hand. In a while loop, move the counter forward before the continue, or switch to a for loop that spares you the bookkeeping.

The second involves finally. A continue placed inside a try does not slip away quietly: the finally block still runs, right before the next turn begins. That is the intended behaviour, since finally exists precisely to release whatever must be released come what may, but it throws people the first time a message appears for an iteration they thought they had skipped.


A concrete case

The pattern really pays off as soon as the rejections have to be accounted for. Here each line of a file is checked against two criteria, and every refusal is logged with its reason at the exact moment it is decided.

PYTHON
valid_rows = 0

for number, line in enumerate(handle, start=1):
    columns = line.split(";")

    if len(columns) != 4:
        report.append(f"Line {number}: missing columns")
        continue

    if not columns[2].isdigit():
        report.append(f"Line {number}: quantity is not a number")
        continue

    store(columns)
    valid_rows += 1

Look at where the error message sits: right against the test that triggered it, on the two lines before the continue. Picking the wrong reason becomes hard, and forgetting to write one becomes hard too: the rejection and its trace form a single gesture.

At the end of the run, report holds a line-by-line account and valid_rows the count of what got through. Written with nested conditions, the same code would have its messages bundled into else branches, far from the matching tests, and the link between a refusal and its explanation would become a matter of careful reading.


Frequently asked questions

Question

What is the difference between continue and break?

continue skips one item and carries on, break stops everything and leaves the loop on the spot. The first filters, the second interrupts. Mixing them up gives a program that seems to handle a single item instead of the whole collection, and it is one of the most baffling bugs early on, because no error is raised to point it out.

Question

Does continue affect the outer loop?

No, it acts only on the loop that directly contains it, exactly like break. With two nested loops, a continue written in the inner loop moves on to the next item of that inner loop, and the outer loop never hears about it. To skip a turn of the outer loop you need a flag, or you move the inner loop into a function of its own.

Question

Is filtering before the loop better?

When the criterion is simple and single, often yes: a list comprehension or a call to filter states the intent in one line and reads at a glance. continue takes the lead again as soon as the criteria multiply, as soon as each one deserves a comment of its own, or as soon as a rejection has to be counted or logged somewhere. Filtering upstream says what you keep, continue says why you drop.

Related terms

Discover our python glossary

Browse the terms and definitions most commonly used in development with Python.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.