NOETRION

Choose a topic

DAY 06 OF 30 · RUN AND REASON

Loops and control flow

Use for and while loops, accumulate results, and explain when break and continue run.

90–120 minutes suggested study timePython 3.12Not yet completed

Today's outcomes

  • Trace each iteration and state change.
  • Choose a bounded or condition-controlled loop.
  • Explain range boundaries, break, continue, and pass.

Before you start: Complete Day 05 and its practical challenge.

Understand the concept

For loops process an iterable one item at a time

A for loop receives successive items from an iterable, binds each item to the loop variable, and executes its block. You can iterate over a list of minute counts without manually referring to the first, second, and third positions. If the iterable is empty, the body runs zero times.

An accumulator carries a result across iterations. Set a total to zero before the loop, add each accepted observation inside it, and inspect the final total afterward. Initializing the accumulator inside the loop resets it on every iteration and usually leaves only the last contribution.

range(stop) produces integers starting at zero and stopping before stop. range(start, stop, step) lets you choose a start and step. It does not include its stop boundary. range(1, 4) therefore produces 1, 2, and 3. A range is not a prebuilt list; Python can iterate it without materializing all those integers as a list.

While loops repeat while a condition stays true

A while loop evaluates its condition before each iteration. Something in the loop must eventually change that condition, or the program may keep running. A countdown reduces a counter; a command loop waits for a quit command; a search may stop when it finds a match. Describe the stopping condition before writing the loop.

For a known collection, start with for. For repetition governed by a changing condition, while can be clearer. Replacing one with the other is possible in many small examples, but the clearer choice communicates why repetition occurs and how it ends.

Break, continue, and pass have different jobs

break exits the nearest enclosing loop. continue skips the remaining statements in the current iteration and proceeds to the next iteration. pass does nothing; it is a placeholder where a statement is syntactically required. It neither exits a loop nor skips the statements that follow it.

A loop's optional else block runs if the loop finishes without break, including when a for loop has no items. That is useful for a search: “not found” is reported only when no match caused an early exit. It is unrelated to an if statement's else meaning, although the keyword is the same.

Worked example

The fictional sessions contain one missing observation. None is skipped rather than converted into a zero-minute session.

sessions = [30, None, 60, 45]
total = 0
recorded = 0

for minutes in sessions:
    if minutes is None:
        continue
    total += minutes
    recorded += 1

print("Recorded sessions:", recorded)
print("Total minutes:", total)

for minutes in sessions:
    if minutes is not None and minutes >= 60:
        print("First full session:", minutes)
        break
else:
    print("No full session found")
Current item Action Total after iteration Recorded count
30 Add observation 30 1
None Continue before addition 30 1
60 Add observation 90 2
45 Add observation 135 3

The search prints First full session: 60 and then breaks. It does not visit 45 in that second loop. The summary loop and search loop answer different questions, so an early exit appropriate for the search would be wrong for the complete total.

Guided practice

  1. Predict: list the values in range(2, 9, 2). Expect 2, 4, 6, and 8. Explain why 9 is excluded and why 10 is never reached.
  2. Modify: change sessions to [0, None, 15]. Expect two recorded sessions and 15 minutes, with no full session found. Zero is retained as a known observation.
  3. Reconstruct: write a countdown from 3 through 1 using while. Decrease the counter on every ordinary iteration. Then trace the values of the counter before and after each decrease.

Do not mutate the source list while iterating today. Day 8 will show why removing elements in place can cause skipped items. Build a separate result or count instead.

Daily challenge

Create a session audit for integer minute counts or None. Treat None as missing, negative numbers as invalid, and nonnegative integers as recorded. Produce recorded_count, missing_count, invalid_count, and total_minutes from accepted observations. The counts must reconcile to the original number of items.

Fixture Recorded Missing Invalid Total
[30, None, -5, 0, 45] 3 1 1 75
[] 0 0 0 0
[None, None] 0 2 0 0
[0, 60] 2 0 0 60

The total is zero for an empty list because it is an additive total under this contract. An average over no observations would need a separate no-data policy. Do not invent an average of zero merely because the total is zero.

Reference solution

Compare after attempting the challenge
sessions = [30, None, -5, 0, 45]
recorded_count = 0
missing_count = 0
invalid_count = 0
total_minutes = 0

for minutes in sessions:
    if minutes is None:
        missing_count += 1
        continue
    if minutes < 0:
        invalid_count += 1
        continue
    recorded_count += 1
    total_minutes += minutes

print("Recorded:", recorded_count)
print("Missing:", missing_count)
print("Invalid:", invalid_count)
print("Total minutes:", total_minutes)
print("Reconciled:", recorded_count + missing_count + invalid_count == len(sessions))

The two continue statements prevent missing or invalid entries from reaching the accepted-observation update. The final reconciliation is an independent accounting check; a total alone would not reveal that the script skipped an item for the wrong reason.

Debug and explain

Symptom Likely cause Check
Only the last item contributes Accumulator reset inside loop Move initialization before repetition
One required day is missing Exclusive range stop misunderstood Trace the actual generated values
Loop never ends While state never reaches stopping condition Inspect the update on every branch
Statements after pass still run pass mistaken for continue Replace only if skipping is intended

Explain why a known zero counts as recorded, why break would corrupt this total, and why an empty iterable still produces initialized counts. At this first checkpoint, rebuild a small script using names, conversion, operators, a branch, and a loop. Identify any concept you can recognize but cannot yet write independently.

Review and next step

Keep the audit outputs and reconciliation for all four cases. Day 7 packages this logic into a reusable function and introduces executable checks. If the audit still needs copied code, repeat the normal and empty cases before moving on.

Sources and verification

Original teaching examples checked with Python 3.12.14. Library behavior reviewed against these primary references on October 3, 2026. Day 26's examples also use Beautiful Soup 4.14.3.

DAILY CHECKPOINT

Check your understanding

Five questions, 20 points each. Pass at 85% or above, which requires all five correct. Feedback explains each answer; revise the lesson and retry when needed.

01. What values does range(3) yield?

02. What does break do?

03. What does continue do?

04. What must a terminating while loop achieve?

05. What does pass do?

Review your practical work

Check these statements after running your own challenge. This is your self-review; the website does not execute or assess your Python code.

Pass the knowledge check and finish the practical self-review to save completion.