1 Before you start
Before you begin, take a few minutes to check what you already know and how confident you feel. You will see the same questions again at the end of the module — this helps both you and us measure what you have learned. Click an option for every question and confidence rating, then click Next to continue.
Inside a for loop, what does break do?
Inside a for loop, what does continue do?
You write for i, x in enumerate(["a", "b", "c"]): print(i, x). What does it print?
You write for i, x in enumerate(["a", "b", "c"], start=1): print(i, x). What does it print?
A break runs inside the inner of two nested for loops. Which loop stops?
Given ids = ["P1", "P2"] and ages = [54, 61], what does for x, y in zip(ids, ages): print(x, y) print?
What does [a * 2 for a in [1, 2, 3]] produce?
Given labels = {"A": 0, "B": 1}, what does {v: k for k, v in labels.items()} produce?
I can explain to a peer the difference between break and continue, and pick the right one for a given task.
I can use enumerate to walk a list and report each item's position alongside its value.
2 Introduction
This module follows on directly from the previous control flow module. By now you can write an if/elif/else chain, walk a list with a for loop, and run a while loop until a condition flips. That is enough for most everyday code. This module covers two refinements that turn up constantly in real work:
- Break and continue — exit a loop early, or skip the current item and go straight to the next one. Stopping at the first significant SNP is
break; ignoring missing values iscontinue. Enumerate— when you need both the position and the value as you loop, like printing a numbered list of samples or reporting which row of a table failed QC.
Try every snippet in the Python Scratchpad on the right. By the end of this module you will write a loop that walks a list, skips missing values, exits the moment it finds what it is looking for, and reports the position alongside the value.
3 Loop control with break and continue
When working with loops, you don't always want them to run from beginning to end. Sometimes you need to alter their path using two distinct tools: break and continue.
Think of break as an eject button. When your code encounters a break statement, the loop stops instantly and completely terminates, with your program immediately moving on to whatever code follows the loop. This is incredibly useful when you have found exactly what you are looking for.

Can you predict what you will get from the code below:
Read the code carefully and type what you think it will print. Click Submit prediction for AI tutor feedback comparing your prediction against the real output, then click Reveal actual output to run the snippet yourself and see what happens.
glucose_readings = [110, 125, 165, 130, 175]
for reading in glucose_readings:
if reading > 160:
print(f"First critical: {reading}")
break
print("Done")
Try and practise the break keyword and the indent level
Try this snippet in the Python Scratchpad on the right.
glucose_readings = [110, 125, 165, 130, 145]
for reading in glucose_readings:
if reading > 160:
print(f"Critical: {reading}")
break
On the other hand, continue does something different. It skips the rest of the current pass and goes straight to the next item. The loop keeps running; only this one iteration is cut short. Use it to filter out items you do not want to process — missing values, blanks, anything that fails a quick sanity check.

Can you predict what will happen with the code below?
Read the code carefully and type what you think it will print. Click Submit prediction for AI tutor feedback comparing your prediction against the real output, then click Reveal actual output to run the snippet yourself and see what happens.
readings = [120, -1, 145, -1, 130]
total = 0
for r in readings:
if r < 0:
continue
total = total + r
print(total)
Try it out!
Try this snippet in the Python Scratchpad on the right.
readings = [120, -1, 145, -1, 130]
for r in readings:
if r < 0:
continue
print(f"Valid: {r}")
You can also combine both break and continue in a single code too!
Both break and continue affect only the loop they are written directly inside. If you have a loop nested inside another loop and you break, only the inner loop ends — the outer one keeps running.

From the example above, you can see two counters side by side. i (left) is the outer loop; j (right) is the inner loop. Each time j hits 3, break fires and j resets to 0. Notice that i keeps incrementing regardless. break only stops the loop it lives in, and the outer loop never sees it.
4 Index tracking with enumerate
Most of the time, when you walk a list, all you care about is each item. But every so often you also need to know its position — you are printing a numbered list of samples, you want to flag which row of a table failed QC, or you need to write the position into a report. enumerate is the tool for that. It hands you both the position and the item on every pass, so you do not have to track the position yourself.

The syntax for enumerate is as follows:
readings = [120, 145, 110]
for i, r in enumerate(readings):
print(f"Patient {i}: {r} mg/dL")Try it out!
Try this snippet in the Python Scratchpad on the right.
samples = ["S001", "S002", "S003", "S004"]
for i, sample in enumerate(samples):
print(i, sample)
If you would rather count from 1 instead of 0 — natural for a numbered list shown to a human — pass start=1 to enumerate. enumerate(samples, start=1) gives you 1, 2, 3, 4 instead of 0, 1, 2, 3. The items are unchanged; only the counter shifts.
Read the code carefully and type what you think it will print. Click Submit prediction for AI tutor feedback comparing your prediction against the real output, then click Reveal actual output to run the snippet yourself and see what happens.
samples = ["S001", "S002", "S003"]
for n, s in enumerate(samples, start=1):
print(f"Sample {n}: {s}")
5 Looping over two lists in parallel with zip
enumerate gives you the position alongside the value of one list.
zip does the same trick for two or more lists at once - it walks them in step. The shape is for a, b in zip(list_a, list_b). Each pass through the loop gives you the next item from each list. This is exactly how you pair a list of patient IDs with a list of ages, or a list of features with a list of labels later on.
Try this snippet in the Python Scratchpad on the right.
patient_ids = ["P001", "P002", "P003", "P004"]
ages = [54, 61, 47, 72]
for pid, age in zip(patient_ids, ages):
print(f"{pid}: {age} years")
# Three lists at once
weights = [82.0, 68.5, 75.1, 90.2]
for pid, age, weight in zip(patient_ids, ages, weights):
print(pid, age, weight)

6 List and dictionary comprehensions
A very common pattern is to walk a list, transform each item, and collect the results into a new list.
You can write that as a three-line for loop, but Python has a one-line shortcut called a list comprehension. The shape is [expression for item in iterable if condition], where the if part is optional. Read it left-to-right like a sentence: "the squared value for each a in ages where a is positive." Comprehensions are everywhere in real Python code, so being comfortable reading them matters.
Try this snippet in the Python Scratchpad on the right.
ages = [54, 67, 71, 49, 82]
squared = [a ** 2 for a in ages]
print(squared)
seniors = [a for a in ages if a >= 65]
print(seniors)
labels = ["senior" if a >= 65 else "adult" for a in ages]
print(labels)

The same shortcut works for dictionaries. The shape is {key_expression: value_expression for item in iterable}. Two common uses are turning a list of pairs into a dict, and building a quick lookup table where the key and value are computed from the same source.
Try this snippet in the Python Scratchpad on the right.
pairs = [("P001", 54), ("P002", 61), ("P003", 47)]
lookup = {pid: age for pid, age in pairs}
print(lookup)
labels = {"A": 0, "B": 1, "C": 2}
inverse = {v: k for k, v in labels.items()}
print(inverse)

7 Putting it together
The two tools in this module almost always combine with the for loop and the if-test you already know. A typical pattern looks like this: walk a list with a for loop, use an if to decide what to do with each item, use continue to skip the items you do not care about, use break to leave the moment you have what you want, and use enumerate when you also need the position.
Let’s practice putting the logic together.
All the lines you need are in the Line bank on the left — some may be distractors you should leave behind. Drag the lines you need into the Your solution column on the right, in the correct order, then click Check.
Task: Loop over patient readings together with their index. Skip invalid (negative) entries. Stop at the first reading above 160 and announce it; otherwise print each valid reading and its patient index.
breakprint(f"Critical at patient {i}")for r in enumerate(readings):continuepassif r < 0:print(f"Patient {i}: {r}")for i, r in readings:if r > 160:readings = [110, -1, 145, 175, 130]for i, r in enumerate(readings):
- Drop lines here, in order.
Good! Now, let’s try the worked example below:
Work through this example in three stages. You unlock each stage only after the tutor confirms the previous one. Each stage removes more of the scaffolding — by the end you are writing it yourself.
Problem: Given a list of p-values, find the position (1-based) and value of the first p-value that is below 5e-8. Skip any None entries while scanning. If none is found, report "none".
p_values = [0.5, None, 0.01, 4.2e-8, 0.001, 1e-9]
result = "none"
for i, p in enumerate(p_values, start=1):
if p is None:
continue
if p < 5e-8:
result = f"position {i}, p = {p}"
break
print(result)
- First we set a default result so we always have something to print, even if no significant p-value is found.
- Then we walk the list with enumerate(start=1) so the position is the human-friendly 1, 2, 3, … instead of 0, 1, 2, ….
- We use continue to skip the None entries cleanly, and break the moment we find a p below threshold so we do not keep scanning.
The same solution with key parts replaced by ???.
Fill in every ??? so the code matches the reference,
then ask the tutor to check it.
Your turn: You have a list of patient creatinine readings. Find the position (1-based) and value of the first reading above 200. Skip any None entries. If none is found, print "all normal". readings = [85, 110, None, 95, 240, 180, 260]
8 Check your understanding
You have reached the end of the module. Try the same questions again — your answers here, paired with your pre-test answers, are how we measure what the module taught you. Answer every question and confidence rating, then click Submit and see results to view your score.
Inside a for loop, what does break do?
Inside a for loop, what does continue do?
You write for i, x in enumerate(["a", "b", "c"]): print(i, x). What does it print?
You write for i, x in enumerate(["a", "b", "c"], start=1): print(i, x). What does it print?
A break runs inside the inner of two nested for loops. Which loop stops?
Given ids = ["P1", "P2"] and ages = [54, 61], what does for x, y in zip(ids, ages): print(x, y) print?
What does [a * 2 for a in [1, 2, 3]] produce?
Given labels = {"A": 0, "B": 1}, what does {v: k for k, v in labels.items()} produce?
I can explain to a peer the difference between break and continue, and pick the right one for a given task.
I can use enumerate to walk a list and report each item's position alongside its value.
9 Your results
Here is how your post-test answers compare with your pre-test answers. The pre/post pairing is the most reliable way to see what this module actually taught you.
Submit the post-test to see your results.
What is the one thing from this module that is still unclear to you?