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 += 1While 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:
- The condition eventually becomes False (update a variable inside the loop), OR
- 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 totalTests
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)"