1.2.18 · D4Introduction to Programming (Python)

Exercises — for loop — iterating over sequences

3,224 words15 min readBack to topic

Level 1 — Recognition (read the loop, predict the output)

You are not writing code yet. You are proving you can trace a loop by hand — pretend you are the computer, holding each item one at a time.

Recall Solution L1.1

The loop hands word each string in order. len(word) counts characters:

  • "sun"3
  • "moon"4
  • "star"4

Output: 3, 4, 4 (three lines). The body ran 3 times — once per item.

Recall Solution L1.2

range(3) produces 0, 1, 2start defaults to 0, stop is excluded. Watch total:

  • start: total = 0
  • i=0: total = 0 + 0 = 0
  • i=1: total = 0 + 1 = 1
  • i=2: total = 1 + 2 = 3

Output: 3. Only the final value prints, because print is outside the loop.

Recall Solution L1.3

A str is a sequence of characters, so ch visits b, a, n, a, n, a. The vowels are the three a's. count climbs 0 → 1 → 2 → 3.

Output: 3.


Level 2 — Application (write a loop for a stated task)

Now you produce the loop. State the goal in words first, then translate to a body that runs once per item.

Recall Solution L2.1
nums = [4, 8, 15, 16, 23, 42]
total = 0
for n in nums:
    total = total + n
print(total)

Why start total = 0? You need a starting accumulator before the loop so the first addition has something to add to. Running the additions: 4, 12, 27, 43, 66, 108.

Output: 108.

Recall Solution L2.2
words = ["hi", "hello", "hey", "welcome", "yo"]
long_count = 0
for w in words:
    if len(w) >= 5:
        long_count = long_count + 1
print(long_count)

Lengths: 2, 5, 3, 7, 2. Those >= 5 are "hello" (5) and "welcome" (7).

Output: 2.

Recall Solution L2.3
squares = []
for i in range(1, 6):     # i = 1, 2, 3, 4, 5
    squares.append(i * i)
print(squares)

range(1, 6) is half-open [1, 6)1, 2, 3, 4, 5. Squaring each: 1, 4, 9, 16, 25.

Output: [1, 4, 9, 16, 25].


Level 3 — Analysis (why does this loop do that?)

Here the code is subtly tricky. Your job is to explain the mechanism, not just the output.

Recall Solution L3.1

The iterator tracks a position number — a counter for "which slot am I on?". Let us call that counter the cursor, written cur (it starts at 0, the first slot, and Python advances it by one after each pass). Crucially, the cursor follows the slot, not the value: when you remove an item, everything after it slides one slot left, but the cursor still steps to the next slot — so it skips the value that slid into the position it just left.

Trace by slot (cursor cur shown):

  • cur=0: slot holds 1, odd → keep. List [1,2,3,4,5,6]; cursor → cur=1
  • cur=1: slot holds 2, even → remove. List becomes [1,3,4,5,6]; cursor → cur=2
  • cur=2: slot holds 4 (the 3 slid into slot 1 and was skipped), even → remove. List [1,3,5,6]; cursor → cur=3
  • cur=3: slot holds 6, even → remove. List [1,3,5]; cursor → cur=4
  • cur=4: no slot there → loop ends.

Output: [1, 3, 5]. Every other even (4, 6) got removed but the one that slid into the current slot each time was skipped.

The figure below shows this row by row: each row is the list at one cursor position. The red slot marks where the cursor currently sits, a yellow outline marks the slot being removed, and the yellow arrow points to the value 3 that slides into slot 1 and is never visited. It exists to make the "skip" visible instead of asking you to hold five list states in your head.

Recall Solution L3.2

zip pairs the i-th items and stops at the shorter sequence. b has only 2 items, so zip yields exactly two pairs, then raises StopIteration. Items 30 and 40 never get a partner.

Output: [(10, 'x'), (20, 'y')]. This is the whole point of zip — no index arithmetic, and no IndexError from over-running the short list.

Recall Solution L3.3

for x in prices: iterates the keys, so x becomes "pen", "book", "bag" (strings). total + x tries to add a string to the integer 0, and Python refuses to add an int and a str. The exact message is:

TypeError: unsupported operand type(s) for +: 'int' and 'str'

To sum the values, loop prices.values():

for v in prices.values():
    total = total + v      # 10 + 50 + 200

which gives 260.


Level 4 — Synthesis (combine tools to solve a real task)

Multiple loop tools working together. Plan in words, then compose.

Recall Solution L4.1
text = "to be or not to be"
counts = {}
for word in text.split():        # ['to','be','or','not','to','be']
    if word in counts:
        counts[word] = counts[word] + 1
    else:
        counts[word] = 1
print(counts)

.split() breaks the string into a list of words; the for visits each. For each word we either start its count at 1 or bump the existing count. Tracing: to→1, be→1, or→1, not→1, to→2, be→2.

Output: {'to': 2, 'be': 2, 'or': 1, 'not': 1}.

Recall Solution L4.2
readings = [3, 7, 2, 9, 4, 9, 1]
best_val = readings[0]
best_idx = 0
for i, v in enumerate(readings):
    if v > best_val:            # strict > keeps the FIRST occurrence
        best_val = v
        best_idx = i
print(best_val, best_idx)

enumerate hands (index, value) pairs so we track both without a manual counter. Using strict > means a later equal 9 does not overwrite — the first 9 at index 3 wins.

Output: 9 3(9, 3).

Recall Solution L4.3
keys = ["a", "b", "c"]
vals = [1, 2, 3]
d = {}
for k, v in zip(keys, vals):
    d[k] = v
print(d)

zip pairs ("a",1), ("b",2), ("c",3); tuple-unpacking splits each into k and v, and we assign into the dict. (See Dictionaries — keys, values, items.)

Output: {'a': 1, 'b': 2, 'c': 3}.


Level 5 — Mastery (build the mechanism / control the flow)

Here you demonstrate you understand the engine and the control-flow keywords, not just the plain syntax.

Recall Solution L5.1

A for loop is sugar for exactly this (see the parent note's derivation). Note the try/except sits inside the while body, indented one level under it:

_it = iter([10, 20, 30])       # 1. get an iterator (cursor at slot 0)
while True:                    # 2. loop forever...
    try:                       #    (this whole try/except is the while body)
        x = next(_it)          # 3. grab next item, advance cursor
    except StopIteration:
        break                  # 4. ...until exhausted -> stop cleanly
    print(x)                   # 5. run the body

Output: 10, 20, 30. This is why for never needs off-by-one index counting: the end is signalled by an exception, not by comparing a counter to a length.

Recall Solution L5.2
items = ["p", "q", "r"]
i = 0
for item in items:
    print(i, item)
    i = i + 1              # manual counter — exactly what enumerate hides
print("after:", i)

The counter i starts at 0, increments once per iteration, and ends at 3 (the number of items). Output: 0 p, 1 q, 2 r, then after: 3. enumerate does exactly this bookkeeping for you — that's why it's cleaner.

Recall Solution L5.3

range(2, 7) gives divisors 2, 3, 4, 5, 6. None divide 7 evenly, so the if never fires, break never runs, and the loop finishes normally. Because no break fired, the else block runs.

Output: prime. (If n were 9, then d=3 would divide it, print not prime, and break — so the else would be skipped.)

Recall Solution L5.4

continue jumps to the next item whenever k is even, so total = total + k runs only for the odd values 1, 3, 5. Adding them: 1 + 3 + 5 = 9.

Output: 9.

Recall Solution L5.5

For each of the 3 values of a, the inner loop runs fully — 2 times. So the body runs 3 times 2 = 6 times. The inner loop finishes before a advances, so pairs come in order: (0,0), (0,1), (1,0), (1,1), (2,0), (2,1).

Output: 6 lines.


Recall Self-check summary (reveal after attempting all)

Level 1 — Recognition

  • L1.1 → 3, 4, 4
  • L1.2 → 3
  • L1.3 → 3

Level 2 — Application

  • L2.1 → 108
  • L2.2 → 2
  • L2.3 → [1, 4, 9, 16, 25]

Level 3 — Analysis

  • L3.1 → [1, 3, 5]
  • L3.2 → [(10, 'x'), (20, 'y')]
  • L3.3 → TypeError (summing prices.values() would give 260)

Level 4 — Synthesis

  • L4.1 → {'to': 2, 'be': 2, 'or': 1, 'not': 1}
  • L4.2 → (9, 3)
  • L4.3 → {'a': 1, 'b': 2, 'c': 3}

Level 5 — Mastery

  • L5.1 → prints 10, 20, 30
  • L5.2 → counter ends at 3
  • L5.3 → prime
  • L5.4 → 9
  • L5.5 → 6 iterations

Connections

  • Parent: for loop — the concepts drilled here.
  • while loop — condition-based repetition — L5.1 desugars for into this.
  • range function — powers L1.2, L2.3, L5.
  • Lists and indexing — the sequence behind most exercises.
  • Strings as sequences — L1.3 and L4.1 .split().
  • enumerate and zip — L3.2, L4.2, L4.3, L5.2.
  • Dictionaries — keys, values, items — L3.3, L4.1, L4.3.
  • List comprehensions — the safe fix in the L3 mistake.
  • Iterators and generators — the iter/next/StopIteration engine in L5.1.

Concept Map

trap

tools

keywords

L1 Recognition trace output

L2 Application write a loop

L3 Analysis explain mechanism

L4 Synthesis combine tools

L5 Mastery build the engine

remove while looping skips items

enumerate zip dict split

break continue for else