← Home

046. While Loop

Repeat while a condition holds

046. While Loop

RAM Manager: Retry Logic

Aryan’s RAM manager polls the OS for process data. Sometimes the data isn’t ready yet. He writes a retry loop — keep trying until it succeeds or times out.

attempts = 0
while attempts < MAX_RETRIES:
    data = read_proc_data(pid)
    if data is not None:
        break
    attempts += 1

While loops are for when you don’t know the count in advance. His count_digits function has a bug — it returns 0 for n=0 because 0 > 0 is False so the loop never runs. His sum_until has an off-by-one: i <= len(numbers) goes one past the end, causing an IndexError.


💡 Fun fact: The infinite loop while True: combined with break is the standard pattern for event loops — the core of every GUI application, web server, and game engine. Node.js, Python’s asyncio, and your browser’s JavaScript engine all run on variations of while True: process_next_event(). The “loop” in “event loop” is literally this construct.

⚠️ Watch out: The most dangerous while loop bug is forgetting to update the loop variable, creating an infinite loop. while n > 0: count += 1 without n //= 10 runs forever. In production, infinite loops silently consume 100% CPU and cause the process to hang — they’re easy to write and hard to notice until the machine slows down.

🤔 Think about it: count_digits(0) needs a special case because 0 > 0 is immediately False and the loop body never executes. Can you think of other while loop patterns where the “zero” or “empty” input case requires a guard before the loop — and what general principle does this suggest about testing loop-based functions?

Learning objectives

  • Write while loops with a terminating condition
  • Handle edge cases (zero, empty input) in while loops
  • Avoid off-by-one errors in loop conditions

Key concepts

  • while loop
  • loop condition
  • termination

Try it

Concept detail

while condition: repeats the block as long as condition is truthy.

You MUST ensure either:

  1. The condition eventually becomes False (update a variable inside the loop), OR
  2. There’s a break statement that exits the loop

Otherwise: infinite loop.

Common while patterns:

Count-controlled (you know the count — use for instead usually)

while count > 0: count -= 1

Sentinel-controlled (run until a special value)

while line != “”: line = read_line()

Retry with max attempts

attempts = 0 while attempts < 3: result = try_operation() if result: break attempts += 1

Event loop (until externally stopped)

while True: event = get_event() if event == QUIT: break handle(event)

while True: + break is a valid pattern for “run until done”. Don’t forget to update the loop variable — a common cause of infinite loops.

Edge case: the body never runs if the condition is False from the start. This is why count_digits(0) needs a special case — 0 > 0 is False immediately.

Solution

def count_digits(n):
    if n == 0:
        return 1
    n = abs(n)
    count = 0
    while n > 0:
        n //= 10
        count += 1
    return count

def sum_until(numbers, limit):
    total = 0
    i = 0
    while i < len(numbers):
        if total + numbers[i] > limit:
            break
        total += numbers[i]
        i += 1
    return total

Tests

def test_count_digits_four():
    assert count_digits(1234) == 4

def test_count_digits_one():
    assert count_digits(7) == 1

def test_count_digits_zero():
    assert count_digits(0) == 1, "0 has 1 digit, but the while loop never runs for 0"

def test_count_digits_negative():
    assert count_digits(-999) == 3

def test_sum_until_basic():
    assert sum_until([10, 20, 30, 40], 55) == 30

def test_sum_until_all():
    assert sum_until([5, 5, 5], 100) == 15

def test_sum_until_no_index_error():
    # i <= len(numbers) goes one past the end, causing IndexError
    try:
        result = sum_until([1, 2, 3], 100)
        assert result == 6
    except IndexError:
        assert False, "IndexError: off-by-one — use i < len(numbers) not i <= len(numbers)"

Resources