In Python, the way you arrange whitespace on the page is not a style preference — it is the syntax itself. Every function, loop, and conditional statement relies on indentation to tell the interpreter which lines of code belong together. Understanding how code blocks work is the foundation of writing any Python program.
Unlike languages that use curly braces or explicit end keywords, Python determines the boundaries of a block purely from the indentation level of each line. This design choice is intentional — it forces the visual layout of a program to match its logical structure, making Python code easier to read at a glance. Once you understand the rule, writing correctly structured code becomes intuitive.
What Is a Code Block?
A code block is a group of statements that Python treats as a single unit. When a block executes, every statement inside it runs in sequence. Blocks can be nested inside other blocks, and the nesting level is reflected directly by the depth of indentation.
Every Python block starts after a compound statement header — a line ending with a colon. The statements that follow, indented further in than the header, form the body of that block. When the indentation returns to the previous level, the block has ended.
# The def line is the block header — it ends with a colon
def greet(name):
# Everything indented here belongs to the greet block
message = "Hello, " + name
print(message)
# This line is back at the original indentation level — outside the block
greet("world")
Python counts leading whitespace on each line and compares it to the current block level. A line with more indentation than the previous one opens a new block. A line with less indentation closes one or more blocks simultaneously and returns to whichever level matches.
Python does not care how many spaces you use per level, as long as every line at the same level uses the exact same amount. The Python style guide (PEP 8) recommends four spaces, and nearly all Python code you will encounter follows that convention.
Build a correct function definition header. Click each token in the right order:
The Colon and the Block Header
Every code block in Python is introduced by a compound statement header that ends with a colon. The colon is not decorative — it is a required part of the syntax that signals to the interpreter that an indented block follows on the next line. Forgetting the colon is one of the most common syntax errors beginners encounter.
The keywords that can appear in a compound statement header include def, class, if, elif, else, for, while, with, try, except, finally, and match. Each of these keywords introduces a new block when followed by a colon.
# Compound statement headers — each ends with a colon
if temperature > 30: # if block
print("It is hot outside")
for item in shopping_list: # for block
print(item)
while count < 5: # while block
count += 1
If Python raises a SyntaxError: expected ':' message, scan the end of the line above where the error was reported. A missing colon after a keyword is almost always the cause.
Python's block syntax differs from other common languages. The table below compares how each language marks block boundaries.
- Block delimiter
- Mandatory indentation (four spaces recommended)
- Block end
- Decrease in indentation level — no closing keyword needed
- Block delimiter
- Curly braces
{ }— indentation is optional and cosmetic - Block end
- Closing curly brace
}
- Block delimiter
- The
dokeyword or curly braces; indentation is optional - Block end
- The
endkeyword or closing brace
The function below has one syntax error. Click the line you think is wrong, then hit check.
def calculate_total(price, tax):. Every compound statement header in Python must end with a colon. Without it, the interpreter raises a SyntaxError before any code runs.
Where Code Blocks Appear
Code blocks are not limited to function definitions. They appear anywhere Python needs to group statements that execute together as a unit. The three places beginners encounter blocks first are function bodies, conditional statements, and loops.
Function Bodies
When you define a function with def, everything indented below the definition line is the function body. That body executes each time the function is called and has access to any parameters passed in.
def describe_temperature(celsius):
# This entire block runs when describe_temperature() is called
fahrenheit = (celsius * 9 / 5) + 32
print(f"{celsius}°C is {fahrenheit}°F")
# Calling the function executes the block above
describe_temperature(100) # output: 100°C is 212.0°F
Conditional Statements
An if statement runs its block only when the condition evaluates to True. Each elif and else branch has its own block, and only the first matching branch executes.
score = 72
if score >= 90:
print("Grade: A") # this block skipped — 72 is not >= 90
elif score >= 70:
print("Grade: C") # this block runs — 72 is >= 70
else:
print("Grade: F") # this block skipped — a previous branch matched
Loops
A for or while loop runs its block repeatedly. Each pass through the loop executes every statement in the block before checking the loop condition or advancing the iterator.
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
# This block runs three times — once per item in the list
upper = fruit.upper()
print(upper)
Nested Blocks
Blocks can be placed inside other blocks. Each additional level of nesting requires another level of indentation. The code below places a conditional block inside a loop block, which is itself inside a function block.
def filter_evens(numbers):
# Function block — 4 spaces
evens = []
for n in numbers:
# Loop block — 8 spaces
if n % 2 == 0:
# Conditional block — 12 spaces
evens.append(n)
return evens # Back to function block — 4 spaces
print(filter_evens([1, 2, 3, 4, 5, 6])) # [2, 4, 6]
Never mix tabs and spaces inside the same file. Python 3 raises a TabError if it detects mixed indentation. Configure your code editor to insert spaces when you press Tab — every modern editor supports this setting.
How to Define Code Blocks in Python
Follow these four steps every time you write a block. The pattern applies identically whether you are defining a function, writing a loop, or branching with a conditional.
-
Write a compound statement header ending with a colon
Start with a keyword such as
def,if,for, orwhilefollowed by the required expression and a colon at the end of the line. The colon tells Python that an indented block follows immediately on the next line. Without the colon, Python raises aSyntaxErrorbefore any code runs. -
Indent every line in the block by four spaces
Press Tab (configured as four spaces) or type four spaces at the beginning of each line that belongs to the block. All lines at the same logical level must use identical indentation. Mixing two spaces on one line and four on the next within the same block causes an
IndentationErrorat runtime. -
Add one or more statements inside the block
Write the statements that should execute when the block is entered. A block must contain at least one statement. If you need a syntactically valid block with no real behavior — for example, while planning code you will fill in later — use the
passkeyword as a placeholder. -
Return to the outer indentation level to close the block
Write the next statement at a lower indentation level to signal the end of the block. Python infers the boundary from the decrease in leading whitespace — no closing keyword or brace is required. If the next line uses the same indentation as the block, Python treats it as a continuation of that block.
"Readability counts." — PEP 20, The Zen of Python
Python Learning Summary Points
- Python uses mandatory indentation — not curly braces — to define code blocks. Every line inside a block must share the same indentation level, and PEP 8 standardizes four spaces per level.
- A new block always begins after a compound statement header that ends with a colon. Keywords that introduce blocks include
def,if,elif,else,for,while,with,try,except, andfinally. - Blocks end when indentation returns to the previous level. Python does not require an explicit closing keyword, so the layout of code on the page directly mirrors its logical structure.
- Nested blocks add one additional level of indentation per layer. A function can contain a loop, which can contain a conditional, each with its own block indented further than the one that contains it.
- The
passkeyword creates a valid empty block. Use it as a placeholder when the block is required syntactically but has no statements to execute yet.
Code blocks are the organizational unit of every Python program. Once the indentation rule is internalized, the structure of even complex programs becomes easy to follow because the visual hierarchy on screen matches the logical hierarchy of the code. Every additional Python concept — classes, decorators, context managers, exception handling — builds on this same foundation.
Frequently Asked Questions
IndentationError in Python 3. Choosing spaces and sticking to four of them per level is the standard convention.
def, class, if, elif, else, for, while, with, try, except, finally, and match. The colon signals that an indented block follows on the next line.
IndentationError is a syntax error raised when Python cannot parse the structure of a program because lines inside a block have inconsistent or missing indentation. It can happen if you forget to indent after a colon, mix tabs and spaces, or un-indent too far out of a nested block.
pass keyword. pass is a no-operation placeholder that satisfies Python's requirement for at least one statement inside every block.
if and for blocks do not create a new scope — variables assigned inside them are available in the enclosing function or module scope.
def statement is not part of that function's block. It belongs to the outer scope — typically module level — and runs independently of the function.