The Python while loop can be used to execute a block of code for as long as a certain condition is fulfilled. While loops are primarily used in Python when the number of it­er­a­tions can’t be de­ter­mined at the time of writing the code. Keep reading to find out how the Python while loop works.

Tip

Teach yourself how to program in Python with our Python tutorial.

What is the while loop in Python?

The Python while loop is a control structure. Control struc­tures determine which path of code will be followed at runtime. In general, loops are used to re­peat­ed­ly execute a block of code. Here’s an overview of the most important control struc­tures in Python:

Control struc­tures in Python Ex­pla­na­tion
If-else state­ments Executes a block of code once, if a condition is fulfilled
While loops Executes a block of code re­peat­ed­ly, as a long as a condition is true
For loops Iterates over elements in a col­lec­tion and executes the block of code for each element

Beginner pro­gram­mers often try to mimic the func­tion­al­i­ty of loops without knowing how they work. Rather than defining a data structure with several elements and pro­cess­ing it with a loop, they define a separate variable for each data set. They also duplicate the code for pro­cess­ing the data sets. The result is sub­op­ti­mal code. This is il­lus­trat­ed in the code below:

person1 = ('Anne', 17)
person2 = ('Marie', 42)
person3 = ('Kate', 63)
print(f"{person1[0]}, {person1[1]} years old")
print(f"{person2[0]}, {person2[1]} years old")
print(f"{person3[0]}, {person3[1]} years old")

In addition to the duplicate code, this approach also has a lo­gis­ti­cal problem: If the number of data sets can’t be defined until runtime, the in­di­vid­ual variables can’t be defined in advance. This is where loops and col­lec­tions of elements come in.

If it is known how many rep­e­ti­tions will be needed at runtime, a Python for loop will be the best option. For example, we can re­for­mu­late the code from above using a for loop. It will then work without any duplicate code and only uses two variables, re­gard­less of the number of data sets involved.

people = ('Jim', 'Jack', 'John')
ages = (17, 42, 63)
for person, age in zip(people, ages):
    print(f"{person}, {age} years old")

On the other hand, you’ll want to use a while loop in Python when you don’t know in advance how many times the code will need to be repeated. For example, say you want to write code for the exchange of messages over an open con­nec­tion. As long as the con­nec­tion is up, messages will be processed. A Python if statement in the body of the loop will evaluate signals and po­ten­tial­ly terminate the con­nec­tion, if called for:

while connection_open():
    print('Ready to receive')
    process_messages()
    if should_close_connection():
        close_connection()
# once loop terminates
print('Connection was closed')

Python while loops are also used for unlimited it­er­a­tions. Some well-known examples are ATMs, the Linux command prompt and the Python Read-Eval-Print loop (REPL). Below we show a sketch of an REPL im­ple­men­ta­tion using an infinite while loop.

# Loop
while True:
    # Read user input
    user_input = read_input()
    # Evaluate input and produce result
    result = eval(user_input)
    # Print result
    print(result)

How does the Python while loop work?

The Python while loop works much like if state­ments in Python. Both of these control struc­tures have two parts:

  1. A condition that will be evaluated
  2. A body with in­struc­tions

The dif­fer­ence between them is how many times the body is executed. The body of an if statement is executed one time, at most:

if condition:
    run_once()

In contrast, the body of a while loop can be executed several times:

while condition:
    run_again()

A Python while loop will run as follows:

  1. The condition is evaluated.
  2. If the condition is true, the body of the loop is executed.
  3. The condition is evaluated again.
    1. If the condition is still true, the process is repeated.
    2. If the condition is false, the loop is ter­mi­nat­ed.

Similar to if state­ments, the while loop in Python can also include an else block. The else block is optional and will be executed once if the condition is (or becomes) false.

while False:
    # this code doesn't loop
    never_runs()
else:
    # instead, this code runs once
    runs_once()

What’s the dif­fer­ence between for loops and while loops in Python?

The Python while loop is related to the for loop. Both of them are used to re­peat­ed­ly execute a block of code. (This is also called “iterating”.) The dif­fer­ence is how many times the code is executed.

In Python, for loops are primarily used to iterate over the elements in a col­lec­tion. The maximum number of it­er­a­tions is limited by the length of the col­lec­tion. Below we iterate over the letters in the word “Python” and output each letter:

for letter in 'Python':
    print(letter)

The Python while loop isn’t based solely on iterating over col­lec­tions. It has a number of flexible uses. The while loop is the more basic loop construct. Whereas a for loop can be con­struct­ed using a while loop, a while loop cannot be con­struct­ed using a for loop.

Let’s look at a few examples. Below we’ll use a while loop to recreate the func­tion­al­i­ty of a typical for loop with a numerical loop variable. To do this, we’ll define a counter variable outside the loop and increment its value within the loop.

counter = 0
limit = 10
while counter < limit:
    print(counter)
    counter += 1

The equiv­a­lent for loop is shorter and more direct:

for counter in range(10):
    print(counter)

Now let’s use a while loop to iterate over the letters in a word. The results will be similar to the above example. We’ll use an iterator and the next() function. If the iterator is exhausted, None will be returned instead of a letter and the loop will be ter­mi­nat­ed. The resulting code is much more com­pli­cat­ed than the equiv­a­lent for loop. A while loop is clearly not the best solution for this problem:

word = 'Python'
letters = iter(word)
letter = ''
while letter is not None:
    letter = next(letters, None)
    if letter:
        print(letter)

Be careful with infinite while loops in Python

Python while loops are es­pe­cial­ly in­ter­est­ing because they can be used to implement infinite loops. At first glance this might seem coun­ter­in­tu­itive, as pro­gram­mers fear ac­ci­den­tal infinite loops. That’s because the condition never becomes false, so the program gets stuck:

while True:
    print("Forever…")

Ac­ci­den­tal infinite loops are usually the result of an ex­pres­sion that always evaluates to True. For example:

while 1 == 1 + 1 - 1:
    print("And ever…")

There are, however, a number of uses for in­ten­tion­al­ly created infinite loops.

Tip

If you find yourself stuck in an infinite while loop in Python REPL, the keyboard shortcut Ctrl + C can help. It will send a stop signal to the Python in­ter­preter, which will then terminate execution of the loop.

Breaking and skipping while loops in Python

A while loop will usually iterate until the loop condition becomes false. A common but prob­lem­at­ic trick is to use a flag variable as the condition. This involves defining a Boolean variable outside of the loop and eval­u­at­ing it in the loop condition. When a certain condition has been reached in the body of the loop, we change the flag variable. When the condition is evaluated in the next iteration, the new value will cause the loop to terminate.

aborted = False
while not aborted:
    print("Still going…")
    if some_cond:
        # will prevent next iteration
        aborted = True

This solution is commonly used but isn’t par­tic­u­lar­ly elegant. What happens when there’s more code in the body of the loop after the flag variable has been changed? The code has to be skipped. Luckily there’s a break statement for while loops in Python.

If a break statement is executed within a loop, the loop will be ter­mi­nat­ed im­me­di­ate­ly. Perhaps you can see the sim­i­lar­i­ty between break state­ments in loops and return state­ments in functions. One dif­fer­ence is, however, that break state­ments don’t return a value. It’s common practice to use a break statement to terminate an infinite loop.

while True:
    print("Still going…")
    if some_cond:
        break
        # we never get here
        print("We shouldn't be here")
# we end up here after breaking
print("Done.")

A close relative of break state­ments are continue state­ments. If a continue statement is executed in the body of the loop, the code following it will be skipped. Execution will continue with the next iteration. Break and continue state­ments can be used to implement simple, text-based menus, like those from early computer games:

# 'continue' takes us here
while True:
    print("Press G to start a new game")
    print("Press S to see stats")
    print("Press M for main menu")
    print("Press Q to quit")
    
    key_press = input("Your choice \n")[0].upper()
    print(f"You pressed {key_press}")
    
    if key_press == "G":
        # start game routines
        print("Starting game …")
    elif key_press == "S":
        # show stats
        print("Showing stats …")
    elif key_press == "M":
        # back to main menu
        print("Returning to menu")
        continue
    elif key_press == "Q":
        # break out of loop
        print("Quitting")
        break
    else:
        print("Unknown command. Try again")
# "break" takes us here
...

How to use while loops in Python

There are a number of diverse uses for while loops in Python. While loops are generally used for al­go­rithms where the number of it­er­a­tions can’t be defined in advance or where that number changes during execution. While loops are often used in com­bi­na­tion with other control struc­tures like decision-making state­ments and try-else state­ments. Let’s look at a few examples.

Consuming a col­lec­tion with while loops in Python

For loops are a good option for iterating over the elements in a col­lec­tion in Python. At least, this is the case as long as the col­lec­tion isn’t changed in the body of the loop. But what happens if we make changes as we go through the elements? Imagine we want to remove elements from the col­lec­tion while iterating. This is referred to as “consuming” a col­lec­tion.

Strange errors can arise when the un­der­ly­ing col­lec­tion in a for loop is changed during iteration. If we want to consume a col­lec­tion, a while loop is the better choice in Python. We’ll make the col­lec­tion the condition of the while loop. As long as the col­lec­tion still contains elements, it will be evaluated to True in a Boolean context. If the col­lec­tion is empty, it will evaluate to False and the loop will terminate.

pieces = ['x', 'o', 'o', 'o', 'x', 'o', 'x', 'x']
while pieces:
    piece = pieces.pop()
    print(f"Removed {piece}")
# test
assert pieces == []

Im­ple­ment­ing your own range() function with while loops in Python

While loops can also be used to implement gen­er­a­tors in Python. A generator is a function that uses a yield statement and generates values on command. Below we’ll create our own im­ple­men­ta­tion of the range() function. We’ll use the yield statement in a while loop to generate con­tin­u­ous numbers. When we reach the yield statement, a value will be returned and the loop will pause.

def my_range(start, stop):
    # only positive ranges implemented
    if stop <= start:
        return None
    current = start
    while current < stop:
        yield current
        # next call of next() continues here
        current += 1
# test
assert list(my_range(7, 9)) == list(range(7, 9))

Op­ti­miz­ing a model using the Python while loop

Op­ti­miz­ing models is part of standard practice in academic dis­ci­plines. It involves cal­cu­lat­ing a model based on a set of pa­ra­me­ters. Af­ter­wards, the pa­ra­me­ters are adjusted and the model is cal­cu­lat­ed again. An objective function is used to estimate whether changing the pa­ra­me­ters resulted in a better model. If so, the process is repeated. This is how iteration can be used to find optimal pa­ra­me­ters for the model.

Normally the model levels off after a number of it­er­a­tions, meaning that im­prove­ment between models will get smaller and smaller. If im­prove­ment falls below a certain value, we’ll terminate op­ti­miza­tion. To make sure that the loop is ter­mi­nat­ed, we’ll set a limit for the maximum number of it­er­a­tions. The following shows this approach for op­ti­miz­ing models using a while loop in Python.

limit = 5
round = 0
progress = True
while progress and round < limit:
    # attempt next optimization
    round += 1
    # compute optimized parameters
    params = optimize(params)
    # make a copy of the old model
    old_model = model
    # compute new model using optimized parameters
    model = run(model, params)
    # worthwhile to continue optimizing?
    progress = has_improved(model, old_model)

Es­tab­lish­ing con­nec­tions with the while loop and im­ple­ment­ing try-except

Es­tab­lish­ing a con­nec­tion doesn’t always work on the first try, which is why multiple attempts are often used. Since we can’t know in advance how many tries will be necessary, we’ll use a while loop. We’ll set a limit on the maximum number of attempts and abort with an error message if none of the attempts were suc­cess­ful.

Here’s the approach we’ll take in Python. We use a try-except statement to catch errors in es­tab­lish­ing a con­nec­tion. The use of a break statement in the try block and a continue statement in the except block will ensure that we iterate correctly. If the con­nec­tion isn’t es­tab­lished, we’ll try again with continue. If the con­nec­tion is es­tab­lished, we terminate the loop using break.

max_tries = 10
attempt = 0
conn = None
# 'continue' takes us here
while attempt < max_tries:
    attempt += 1
    print("Trying to get a connection")
    try:
        # might raise 'ConnectionException'
        conn = get_connection()
        # got our connection
        break
    # "get_connection()" raised 'ConnectionException'
    except ConnectionException:
        print("Something went wrong. Trying again")
        continue
# went through 'max_tries' unsuccessful connection attempts
else:
    assert conn is None
    print("Unable to connect")
# 'break' takes us here
assert conn is not None
print("Connection established")

Iterating over recursive struc­tures with the Python while loop

The while loop in Python is well suited to solving recursive problems. This means that it’s a good option for iterating over:

  • Embedded lists
  • Tree struc­tures
  • Graphs

Let’s look at how that works using the example of Russian nesting dolls. The toy consists of wooden dolls that nest inside of each other. From the outside, it’s im­pos­si­ble to know how many dolls are inside, so we’ll take an iterative approach. We’ll open the first doll and see what we find inside. If there’s another doll, we repeat the process. This is a typical use case for while loops.

We can model the dolls as embedded lists that each contain a single element. The lists will either contain another list or an object that’s not a list. We’ll literate over a doll as long as it’s a list. In the body of the loop, we’ll use an as­sign­ment to go one level deeper. At some point we’ll find an element that’s not a list. At that point the iteration will terminate.

def open_doll(doll):
    """
    * Dolls dolls stacked five levels deep, with 'None' inside:
    'doll = [[[[[None]]]]]'
    """
    while type(doll) is list:
        print("Opening the next doll")
        # go one level deeper
        doll = doll.pop()
    else:
        print(f"Reached the bottom and found {doll}")
        return doll
# test
doll = [[[[[None]]]]]
assert open_doll(doll) is None

This simple approach works re­gard­less of how deeply embedded the doll is. Our algorithm will dig to the bottom and reveal the embedded object. That’s the magic of Python while loops in action.

Running a Python while loop on a game board

Another frequent use for Python while loops is moving pieces in boardgames. If you want to make sure to cover all fields, you’ll need two loops embedded in each other. But be sure to pay attention to the runtime. Under certain cir­cum­stances the program can run for a very long time.

We implement a simple “random walk” in which the character moves randomly until it arrives at a des­ti­na­tion. This kind of movement pattern is similar to the movement of a particle in liquid or a fly flying around a room. Since it’s not known in advance how many it­er­a­tions will be needed, this is a job for the while loop.

First we’ll define the function random_walk(), which will contain the while loop. With the Python operator for “equal to”, we’ll check whether the character’s current location is its des­ti­na­tion. If not, we iterate again.

def random_walk(board = (10, 10), goal = (4, 4), start = (0, 0)):
    # ensure arguments are valid
    if not (goal[0] in range(board[0]) and goal[1] in range(board[1]) and start[0] in range(board[0]) and start[1] in range(board[1])):
        print(f"Goal {goal} and / or start position {start} outside of board with dimensions {board}")
        return None, 0
    steps = 0
    pos = start
    # as long as we haven't reached the goal
    while not pos == goal:
        # move to neighboring position
        pos = get_neighbor(pos, board)
        steps += 1
        print(f"Moved to position {pos}")
    print(f"Reached goal at {pos} after {steps} steps")
    return pos, steps

We’ll also define a helper function get_neighbor(), which will return the field around a certain location.

def get_neighbor(pos, bounds):
     from random import choice
     """
          x = 0     . . .     m
                - - - - - - - -
      y = 0 |
              |
            . |              (x, y-1)
            . |  (x-1, y) (x, y)  (x+1, y)
            . |              (x, y+1)
              |
            n |
    
     """
     x, y = pos
     # computer neighbors
     neighbors = [ (x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1) ]
     # filter out neighbors that are outside of bounds
     neighbors = [ pos for pos in neighbors if 0 <= pos[0] < bounds[0] and 0 <= pos[1] < bounds[1] ]
     # select a random neighbor
     neighbor = choice(neighbors)
     return neighbor

Finally, we’ll test our random walk im­ple­men­ta­tion.

random_walk(board = (10, 10), goal = (4, 4), start = (5, 7))
Go to Main Menu