Concepts / Loops and Indentation

Loops and Indentation

Indentation is required syntax in Python, not optional formatting. Leading whitespace determines how statements are grouped into blocks.

  • Programming
Interactive lab

Try it: Syntax Errors and Indentation

How Python checks a program's structure before running any of it: the tokenizer tracks indentation with a stack (INDENT and DEDENT), the parser groups lines into blocks after each colon, and when something is wrong Python reports the exact SyntaxError, IndentationError or TabError with the line, a caret under the spot and hints like "Did you mean '=='".

How it works

  1. The tokenizer reads each line's leading spaces: deeper than the top of the indentation stack is an INDENT (pushed), shallower pops DEDENTs until it matches, and a width that matches no open level is an IndentationError.
  2. Tabs count as 8 columns and as 1; if the two ways of counting disagree about the block structure, it is a TabError.
  3. Inside ( [ { line breaks and indentation are ignored, so a missing ) swallows the following lines; Python reports "'(' was never closed" when the error is found on a later line.
  4. The parser matches statements: a header such as if, for, while, def or else must end with ':' and be followed by an indented block; = where a condition is expected, or a keyword used as a name, is invalid syntax.
  5. Python stops at the first error and prints File, line, the source line, a caret (^) under the columns it blames, and the error type and message; no line of the program has run.

Default run (4 steps): main.py has 7 lines. Before running any of it, Python compiles the whole file: the tokenizer splits each line into tokens and tracks indentation, and the parser groups the statements into blocks. … Python stops: SyntaxError: expected ':' (line 2). No line of the program has run.

Simplified: The programs are fixed and you break them with one menu choice at a time. The lab's own small Python tokenizer and parser (written for the statements these programs use: assignments, print calls, if / elif / else, for, while, def and return) checks the text; nothing is executed as real Python. Every program the lab can show was compiled by CPython 3.12 and the lab reproduces its exception type, message, line, caret columns and the printed report. Only the error kinds offered in the menu are modelled.

Educational simulation

Loading the simulation…

Why Whitespace Carries Meaning

In many languages, spaces at the start of a line are only a matter of style. Python is different. Indentation is required syntax, not optional formatting. The amount of leading whitespace on a line tells Python how that line relates to the lines around it. A loop is a good place to see this, because the statements that should repeat must be grouped together, and indentation is how that grouping is written down.

Keep one question in mind as you read: when Python reaches a line, how does it know whether that line belongs to the loop or comes after it? The answer, as the rest of this article shows, is the leading whitespace.

Tracing a Loop Body Line by Line

Read the program below and trace it as Python would. The loop header ends with a colon. The line that follows, indented further, is the loop body. Python runs that body once for each item in the list. The final line is not indented at all, so it is not part of the loop.

python
Output (expected)
1
2
3
done
Notes on the code
  • The for line starts the loop and ends with a colon
  • The indented print(n) is the loop body and runs once per item
  • The unindented print("done") is outside the loop and runs once, after the loop finishes

What do you think happens?

Before reading the output, what do you think this program prints, and how many times does print(n) run?

  • 1, 2, 3, then done

  • done only

  • 1, 2, 3, done, and then print(n) runs again

Reveal answer
Answer:

1, 2, 3, then done

The indented print(n) runs once for each of the three items, so it prints 1, 2, and 3. The unindented print("done") runs once after the loop has finished, so the output ends with done. Only the indented line repeats.

Reading Blocks from Leading Whitespace

Definition

A block is a group of statements that Python treats as one unit. In Python, leading whitespace determines how statements are grouped into blocks. Statements at the same indentation level belong to the same block. A statement with more indentation than the line before it starts a new, deeper block.

for n in numbers:header, ends with a colonprint(n)indented: inside the loopbodyprint("done")not indented: runs afterthe loopbodyblock ends
Which lines are inside the loop body and which run after the loop finishes, based only on their leading whitespace?

Notice what the diagram shows. Nothing in the code says repeat or stop. The only thing separating the loop body from the statement after the loop is how far each line is indented. When the indentation returns to the level of the for line, the block has ended.

What runs on each pass through the loop, and when does control leave the indented block?

The indented body runs once for each item. Each pass uses the next value of n. When the items run out, Python leaves the indented block and continues with the first unindented line that follows it.

Recognizing and Fixing an IndentationError

An IndentationError occurs when Python finds indentation where it does not expect it, or when indentation is inconsistent. You cannot start a new block whenever you like. A block opened by a line ending in a colon must be followed by an indented body. The before and after versions below show the most common case: the body is missing its indentation.

Before
for n in [1, 2, 3]:
print(n)

The for line ends with a colon, but the next line is not indented, so Python finds no block body. This raises an IndentationError.

After
for n in [1, 2, 3]:
    print(n)

The print line is indented one level under the for line. The block is complete, and the program runs, printing 1, 2, and 3.

When you see an IndentationError, check three things in order: whether the line after a colon is indented, whether lines that belong to the same block have the same amount of leading whitespace, and whether the file mixes tabs with spaces. Mixing tabs and spaces is a named cause of indentation errors, so the fix is to use one kind of indentation throughout the file.

Choosing Four Spaces Per Level

The official Python standard is four spaces per indentation level. Every example in this article follows that rule. The standard exists so that code written by different people looks the same, and so that the visual hierarchy of nested blocks is easy to read at a glance.

Key point

Consistency is the critical part. The number four is the agreed standard, but what makes indentation work is using the same amount, with the same kind of character, at each level. Mixing spaces and tabs, or using an inconsistent number of spaces, causes errors.

Required Versus Optional Indentation

Indentation is required wherever Python expects a block. After a loop header or an if header, the body must be indented. Within a block, every statement at the same level must line up. Where indentation changes block structure, it is syntax, and getting it wrong raises an error or silently changes the program.

SituationWhat indentation doesWhat to do
Line after a loop or if headerStarts the block body; requiredIndent the body, consistently
Statement at the same level as the loopEnds the loop body; changes meaningAlign with the header only when it should run after the loop
Nested block inside anotherDefines a deeper level; requiredAdd one consistent level per nesting step
Mixing tabs and spaces within a fileCauses errorsUse one kind of indentation throughout

Where indentation is structural and where its mistakes show up

Practice Tracing Nested Blocks

MEDIUM

Without running the code, predict the output of the program below. Then check which lines are inside the loop body and which run after it, using only the leading whitespace.

items = [4, 7]
for x in items:
    if x > 5:
        print("big")
    print(x)
print("finished")
Hints
  • Find the for line and the lines indented under it first
  • The if statement has its own body, indented one level further
  • The print(x) line is at the same level as the if line, so it runs for every item
EASY

Take the broken loop from the IndentationError section and write a corrected version that prints each item and then prints finished after the loop. Use four spaces for every indentation level.

Hints
  • Indent only the lines that belong to the loop body
  • Leave the final print unindented

Key Takeaways

  • Leading whitespace determines how statements are grouped into blocks, and indentation is required syntax in Python.
  • A loop body is the indented block that runs once per item; the first unindented line after it runs after the loop finishes.
  • An IndentationError appears when indentation is missing where a block is expected, or when it is inconsistent or mixes tabs and spaces.
  • The official standard is four spaces per level, and consistency matters more than any single number.
  • Nested blocks each add one more level of indentation, and each statement belongs to the nearest block above it with less indentation.

Related concepts

More concepts starting with L