The while Loop

while repeats for as long as a condition holds. Use it when the number of repetitions is unknown, and make sure something inside the loop can make the condition false.

The shape of a while loop

count = 1

while count <= 5:
    print(count)
    count += 1          # without this line the loop never ends

print("done")

Three things must be present: the condition is initialised before the loop, it is tested at the top of every iteration, and something inside the body moves it towards becoming false. Missing the third is how infinite loops happen.

for or while?

Use for whenUse while when
You have a collection to walk throughYou are waiting for a condition to change
The number of repetitions is known in advanceThe number of repetitions is unknown
Iterating a list, string, file or rangeReading input until the user stops
Almost always, in practiceMenus, retries, simulations, games
# A counting loop written as while: possible, but not idiomatic
i = 0
while i < 5:
    print(i)
    i += 1

# The same thing as a for loop
for i in range(5):
    print(i)

Reading input until a sentinel

total = 0

while True:
    entry = input("Amount (or 'done'): ")
    if entry == "done":
        break
    total += float(entry)

print("Total:", total)

while True with a break is a normal and readable Python pattern when the exit test naturally sits in the middle of the body. It is not a code smell, as long as there is a clear and reachable break.

The same loop with the walrus operator

while (entry := input("Amount (or 'done'): ")) != "done":
    print("Recorded", entry)

Validating input

while True:
    raw = input("Enter your age: ")
    if raw.isdigit() and 0 < int(raw) < 130:
        age = int(raw)
        break
    print("Please enter a whole number between 1 and 129.")

print("Age recorded:", age)

Retrying with a limit

MAX_ATTEMPTS = 3
attempts = 0
connected = False

while attempts < MAX_ATTEMPTS and not connected:
    attempts += 1
    print(f"Attempt {attempts}...")
    connected = attempts == 3       # stands in for a real operation

if connected:
    print("Connected")
else:
    print("Gave up after", attempts, "attempts")

Every retry loop needs an upper bound. A loop that retries until it succeeds will hang forever the day the thing it is waiting for never comes back.

notes = []

while True:
    print("\n1 Add  2 List  3 Quit")
    choice = input("Choose: ").strip()

    if choice == "1":
        notes.append(input("Note: "))
    elif choice == "2":
        for index, note in enumerate(notes, start=1):
            print(index, note)
    elif choice == "3":
        print("Goodbye")
        break
    else:
        print("Not a valid choice")

Consuming a collection

queue = ["job1", "job2", "job3"]

while queue:                       # truthy while it has items
    job = queue.pop(0)
    print("processing", job)

print("queue empty")

while queue: reads naturally and terminates because pop shortens the list every time. This is the classic shape for processing a work queue.

Infinite loops and how they happen

# 1. The counter is never advanced
i = 0
while i < 5:
    print(i)        # i never changes

# 2. The advance is outside the loop body
i = 0
while i < 5:
    print(i)
i += 1              # wrong indentation, runs once after the loop

# 3. The condition can never become false
value = 1
while value != 0:
    value -= 2      # 1, -1, -3, ... it steps straight past zero

# 4. A float comparison that never lands exactly
x = 0.0
while x != 1.0:
    x += 0.1        # never exactly 1.0

Case four is worth remembering: never test a float for exact equality in a loop condition. Use < or >, or count in integers.

If a loop hangs, press Ctrl+C to interrupt it. The traceback shows the line it was executing, which is usually the line that should have changed the condition.

while with else

n = 29
divisor = 2

while divisor * divisor <= n:
    if n % divisor == 0:
        print(n, "is not prime")
        break
    divisor += 1
else:
    print(n, "is prime")

The else block runs only if the loop finished because its condition became false, never if it exited through break. Read it as "no break happened". It is covered further in the loop control note.

Common mistakes

  • Forgetting to advance the counter, or advancing it outside the body.
  • Writing while True: with no reachable break.
  • Testing a float for exact equality.
  • Using while to walk a list when for would do it without an index.
  • Retrying with no maximum attempt count.
  • Modifying the condition variable in only one branch of an if inside the loop.

Best practices

  • Prefer for unless the repetition count is genuinely unknown.
  • Before writing the body, write the line that will eventually end the loop.
  • Put a hard limit on every retry or polling loop.
  • Use while collection: when consuming items; it reads well and terminates naturally.
  • Keep the body short. If it grows past a screen, extract a function.

Practice

  1. Write a number guessing game that gives higher or lower hints and counts the attempts.
  2. Sum numbers entered by the user until they type a blank line.
  3. Write a loop that reverses the digits of an integer using % and //.
  4. Explain each of the four infinite loop examples above and fix them.
  5. Rewrite a while loop that walks a list by index as a for loop.

Conclusion

Use while when you do not know how many repetitions there will be, and always know how the loop ends before you write what it does. while True with a clear break is idiomatic; a loop with no exit is a hang waiting to happen.

Written by Lorens Mishra

Default administrator account created by the installer.

Continue reading

All Python notes →
Python

The for Loop and range()

A Python for loop walks over the items of a collection directly. range() supplies numbers when you genuinely need a counter, which is less often than...

Read more

Discussion

0 comments
Sign in to join the discussion.

No comments yet. Be the first to say something.