For, Range, and Iteration Patterns

Key Takeaways

  • A for loop assigns the next item from an iterable to the loop variable on each iteration.
  • range(stop) starts at 0 and excludes stop; range(start, stop, step) also excludes stop.
  • A negative range step counts downward only when start is greater than stop; a zero step raises ValueError.
  • After a for loop that ran at least once, the loop variable keeps its last assigned value.
  • PCEP range traps usually involve excluded stop values, empty ranges, negative steps, or confusing values with indexes.
Last updated: June 2026

What a for loop does

A for loop pulls values from an iterable one at a time. On each pass Python assigns the next value to the loop variable and runs the indented body.

for ch in 'PCEP':
    print(ch)

Here ch becomes 'P', 'C', 'E', then 'P'. No manual index is required unless the code genuinely needs positions.

The range function

range() is the most common PCEP loop source. It produces a sequence of integers lazily (it does not build a list).

FormValues producedNote
range(4)0, 1, 2, 3start defaults to 0
range(2, 6)2, 3, 4, 5stop is excluded
range(1, 8, 2)1, 3, 5, 7step is 2
range(5, 1, -1)5, 4, 3, 2counts down
range(3, 3)(nothing)empty range

The stop value is never included — the single biggest source of off-by-one mistakes on the exam. To loop 1 through 5 inclusive, write range(1, 6).

Negative steps and empty ranges

A negative step moves downward, and start must exceed stop to produce any values.

print(list(range(5, 0, -2)))  # [5, 3, 1]
print(list(range(0, 5, -1)))  # []

The second range is empty: it begins at 0 and tries to descend toward a higher stop of 5, so it is already past the boundary. A step of 0 raises ValueError because the range could never advance.

Iterating over data versus indexes

For loops iterate directly over strings, lists, and tuples:

letters = ['a', 'b', 'c']
word = ''
for letter in letters:
    word += letter.upper()
print(word)   # ABC

When you need positions, use range(len(data)):

items = [10, 20, 30]
for i in range(len(items)):
    print(i, items[i])

Do not confuse the index with the item. In for item in items, item is 10, 20, 30. In for i in range(len(items)), i is 0, 1, 2 — the position, not the value. PCEP also tests enumerate, which yields index/value pairs: for i, v in enumerate(items) gives (0, 10), (1, 20), (2, 30).

Trace-table method

Write the iteration list first, then trace body variables.

SourceLoop values
range(2, 9, 3)2, 5, 8
'cat''c', 'a', 't'
[4, 1]4, 1
Iterationntotal beforeoperationtotal after
120add 22
252add 57
387add 815

Loop variable after the loop

If a for loop runs at least once, the loop variable survives the loop and holds its last value. After for n in range(3):, n equals 2. If the loop never ran (an empty range) and the variable was not defined earlier, reading it afterward raises NameError. PCEP uses this to check whether you noticed an empty range.

Nested for loops

Nested loops multiply iterations: an outer loop of 3 and an inner loop of 2 runs the inner body 6 times. The inner loop completes fully for each single outer value before the outer advances.

Exam traps

Do not assume a loop runs just because it is written; an empty range runs zero times. Do not include the stop value. Do not assume the loop variable resets after the loop. And always read whether the code iterates over values or indexes before predicting the output.

Counting iterations of a range

PCEP often asks how many times a loop body runs rather than what it prints. For range(start, stop, step) with a positive step, the count is (stop - start + step - 1) // step floored at zero, but the reliable exam method is simply to list the values.

RangeValuesIterations
range(5)0,1,2,3,45
range(2, 10, 2)2,4,6,84
range(10, 2, -3)10,7,43
range(4, 4)(none)0

The last case is the trap: equal start and stop produce an empty range, so the body never runs and a loop variable defined only inside is never created.

Accumulating across a range

Many items combine a range with a running total or product. List the values, then fold them in.

product = 1
for n in range(1, 5):
    product *= n
print(product)   # 24

The values 1, 2, 3, 4 multiply to 24 (factorial of 4). Starting product at 0 instead of 1 would wrongly give 0, a deliberate distractor.

Iterating a string by index versus by character

name = 'abc'
for i in range(len(name)):
    print(i, name[i])

This prints index/character pairs 0 a, 1 b, 2 c. Compare with for c in name:, which yields only the characters. Confusing these is one of the most tested distinctions in this domain.

Reading checklist for for/range questions

  1. Write out the exact iteration values before anything else.
  2. Confirm whether the loop iterates over values, characters, or indexes.
  3. Check for an empty range (equal bounds, or a step pointing the wrong way).
  4. Trace each changing variable in its own column.
  5. Note the loop variable's final value in case the question reads it after the loop.
PitfallGuard
Including the stop valueStop is always excluded
Wrong-direction negative stepStart must exceed stop to descend
Zero stepRaises ValueError
Index vs value confusionDecide which the loop variable holds first

With the iteration list written down, for-loop questions reduce to simple arithmetic, and the empty-range and stop-exclusion traps lose their bite.

Test Your Knowledge

What is printed by this code? total = 0 for n in range(1, 7, 2): total += n print(total)

A
B
C
D
Test Your Knowledge

Which range produces the values 6, 4, 2?

A
B
C
D
Test Your Knowledge

What is printed by this code? text = 'py' for ch in text: print(ch * 2, end='')

A
B
C
D
Test Your Knowledge

What does enumerate(['a', 'b']) yield on its first iteration when unpacked as for i, v?

A
B
C
D