Python online course

Nested Loop Statements in Python

Learn how nested Python loops work, trace outer and inner loop execution, and build a while loop containing a for loop with range().

A nested loop is a loop contained inside another loop. The loop that contains the other loop is the outer loop. The loop inside it is the inner loop.

When Python reaches a nested loop, it enters the outer loop and then runs the inner loop as part of that outer-loop iteration. The inner loop normally completes all of its iterations before Python returns to the outer loop and starts its next iteration.

This lesson assumes that you know variables, input(), while loops, for loops, and range(). For related fundamentals, see the Python for loop, the Python while loop, and using for with range().

How nested loops execute

Consider this structure:

while outer_condition:
    for item in sequence:
        inner_statement
    statement_after_inner_loop

For each iteration of the while loop, Python does the following:

  1. Tests the outer loop condition.
  2. Enters the outer loop if the condition is true.
  3. Runs the entire inner for loop.
  4. Runs any statement that is indented at the outer-loop level after the inner loop.
  5. Returns to the outer loop and tests its condition again.

A new inner-loop cycle begins when the outer loop begins another iteration. Therefore, if the outer loop runs three times and the inner loop prints four values each time, the inner loop produces twelve printed values in total.

Example: a while loop containing a for loop

The following program repeatedly asks for a number. A value of 0 is a sentinel value: it tells the program to stop. For every other entered number, the inner loop prints integers from 1 up to, but not including, that number.

number = int(input("Enter a number (0 to stop): "))

while number != 0:
    for value in range(1, number):
        print(value)

    number = int(input("Enter a number (0 to stop): "))

The program uses int() because input() returns text. Numeric comparison with 0 and use as the stop value for range() require an integer. For example, int("5") produces the integer 5.

The second input statement is important. It is indented inside the outer while block but outside the inner for block. This requests a new value once after the inner loop finishes. The new value is then tested by the outer loop condition.

Reading the execution

User inputOuter while condition resultInner for-loop valuesNext action
55 != 0 is true1, 2, 3, 4Ask for another number
1212 != 0 is true1, 2, 3, ..., 11Ask for another number
00 != 0 is falseDoes not runEnd the outer loop and finish

With input 5, the outer loop starts one iteration. The inner loop runs four times and prints 1, 2, 3, and 4. The program then asks for another number.

If the next input is 12, the outer loop starts another iteration. The inner loop is created again for this iteration and prints 1 through 11. When the user finally enters 0, the condition is false, so Python skips the inner loop and exits the outer loop.

Understanding range() boundaries

range(start, stop) starts with start and stops before stop. The stop value is exclusive.

ExpressionValues generated for x = 5Whether x is included
range(1, x)1, 2, 3, 4No
range(1, x + 1)1, 2, 3, 4, 5Yes

Use range(1, number) when the output should end at number - 1. To include the entered number, use range(1, number + 1):

number = int(input("Enter a number: "))

for value in range(1, number + 1):
    print(value)

For an input of 5, the first version prints 1 through 4, while the inclusive version prints 1 through 5.

Indentation defines loop scope

In Python, indentation defines which statements belong to a code block. In the example below, print(value) belongs to the inner loop and runs once for every value. The second print() belongs to the outer loop and runs once after the inner loop completes.

while number != 0:
    for value in range(1, number):
        print(value)              # Runs for every inner-loop value

    print("Sequence complete")    # Runs once after the inner loop

The next input operation should have the same indentation as the for statement, not the indentation of its body:

while number != 0:
    for value in range(1, number):
        print(value)

    number = int(input("Enter a number (0 to stop): "))

If the input statement is placed inside the for body, the program requests input after every printed value. That changes the behavior and can make the program appear to request input too often.

Sentinel-controlled termination

A while loop is a condition-controlled loop: it continues while its condition is true. Here, number != 0 means “continue while the entered number is not zero.” The special value 0 is the sentinel that ends repetition.

The value tested by the loop condition must change during the loop. In this program, the final input statement updates number on every outer-loop cycle. If that statement is missing, number keeps its original nonzero value and the program can become an infinite loop.

Do not manually update a for-loop variable

A for loop automatically assigns each successive value generated by range() to its loop variable. You do not need to increment that variable yourself.

for value in range(1, number):
    print(value)

In this loop, range() supplies the next value. Adding value += 1 does not control what value the next iteration receives; Python assigns the next value from the range anyway. It can also skip or confuse values within the current iteration, so remove unnecessary manual updates.

Another nested-loop pattern: rows and columns

Nested loops are useful when one repeated task contains another repeated task. Common beginner examples include rows and columns, multiplication patterns, coordinate pairs, and processing each item within several groups.

for row in range(1, 4):
    for column in range(1, 5):
        print(f"({row}, {column})")

The outer loop selects rows 1, 2, and 3. For each row, the inner loop completes all four column values. Each row therefore produces coordinates with columns 1 through 4 before the next row begins.

Troubleshooting nested loops

The program never stops

The variable used in the while condition may never be requested or updated again. Read a new value during each outer-loop cycle and make sure the user can enter the sentinel value 0.

The output includes the entered number unexpectedly

range(1, number + 1) includes the endpoint. Use range(1, number) when the intended output ends at one below the entered number.

The output does not include the entered number

This is the normal exclusive-stop behavior of range(). Use range(1, number + 1) when the upper endpoint should be included.

An IndentationError occurs or input is requested too often

Check which block each statement belongs to. The output statement should be inside the inner loop. The next input statement should be inside the outer while block but outside the inner for body.

A manual increment seems ineffective

A for loop gets its next value from the iterable, such as range(). Remove manual updates to the loop variable.

A ValueError occurs after text is entered

int() cannot convert arbitrary text into an integer. Enter a whole number for this basic example. Later, you can add validation with exception handling; see try and except statements.

Key points

  • Nesting places one loop inside the body of another loop.
  • The outer loop controls when the inner loop starts.
  • The inner loop normally completes before the outer loop starts its next iteration.
  • range(1, x) produces values from 1 through x - 1.
  • Use range(1, x + 1) when x should be included.
  • Indentation determines whether code repeats inside the inner loop or runs once afterward.
  • A sentinel-controlled while loop needs an updated condition variable so it can terminate.
  • A for loop automatically receives successive values; do not manually increment its loop variable.