How to indent in Python

Learn how to indent in Python. Discover different methods, tips, real-world applications, and how to debug common indentation errors.

How to indent in Python
Published on: 
Fri
Feb 20, 2026
Updated on: 
Mon
Apr 6, 2026
The Replit Team

In Python, correct indentation is not just for style; it defines your code’s structure and logic. The language uses whitespace to group statements, so proper formatting is essential for your code to run.

You'll explore key techniques and practical tips for indentation. This includes real-world applications and debugging advice to help you write clean, functional Python code every time.

Basic indentation in Python

if True:
print("This line is indented")
print("This line is also indented")
print("This line is not indented")--OUTPUT--This line is indented
This line is also indented
This line is not indented

This snippet highlights how indentation dictates which code runs and when. The key takeaway is that statements indented under the if True: line belong to that conditional block. Understanding the fundamentals of using if statements in Python is crucial for proper indentation.

  • The two indented print() statements are grouped. They only execute because the if condition is true.
  • The final print() statement is unindented. This places it outside the block, so it runs independently after the conditional code.

Alternative indentation approaches

While the standard four-space indent is a solid foundation, you'll encounter other styles in practice, each with its own impact on code clarity.

Using tabs instead of spaces

if True:
print("This line is indented with a tab")
if False:
print("This is nested indentation with tabs")
print("Back to no indentation")--OUTPUT--This line is indented with a tab
Back to no indentation

While tabs can define code blocks, they introduce potential pitfalls. In the example, the first print() executes correctly, but the nested block under if False: is skipped as expected.

  • The main risk is accidentally mixing tabs and spaces. This common mistake can trigger a TabError and break your code.
  • For this reason, the official PEP 8 style guide strongly recommends using four spaces per indentation level to ensure consistency across different editors.

Using 2 spaces instead of 4

if True:
print("This line uses 2 spaces")
for i in range(3):
print(f"Nested with 2 spaces: {i}")--OUTPUT--This line uses 2 spaces
Nested with 2 spaces: 0
Nested with 2 spaces: 1
Nested with 2 spaces: 2

Using two spaces is another valid approach, and your code will run without issues as long as you're consistent. In the example, both the print() function and the for loop are indented by two spaces, correctly placing them inside the if block.

  • This style saves horizontal space, which can be useful for deeply nested code.
  • The main trade-off is readability. Fewer spaces can make it harder to quickly see the structure of complex logic compared to the four-space standard.

Multi-level indentation with nested blocks

x = 10
if x > 5:
print("x is greater than 5")
if x < 15:
print("x is less than 15")
for i in range(2):
print(f"Nested loop: {i}")--OUTPUT--x is greater than 5
x is less than 15
Nested loop: 0
Nested loop: 1

This example shows how you can nest code blocks to create more complex logic. Each level of indentation pushes the code deeper, creating a new scope. The execution flows from the outermost block inward, as long as each condition is met.

  • The first if x > 5: statement creates the top-level block.
  • Because its condition is true, the nested if x < 15: block is evaluated next.
  • Finally, the for loop executes because it’s inside the second if block, which also passed.

Advanced indentation techniques

While block indentation is crucial, Python also handles formatting elegantly in more advanced cases like if expressions, list comprehensions, and parenthetical line continuations.

Working with if expressions

x = 10
result = ("x is even" if x % 2 == 0 else
"x is odd")
print(result)--OUTPUT--x is even

This compact syntax, known as a conditional expression, is a one-line shortcut for a simple if-else statement. It’s an elegant way to assign a value to a variable based on a condition.

  • The expression follows the structure value_if_true if condition else value_if_false. Here, result becomes "x is even" since x % 2 == 0 evaluates to true.
  • The parentheses () allow the expression to be split across lines for readability. Indentation inside parentheses is flexible and used for alignment, not for defining a code block.

Indentation in list comprehensions

numbers = [1, 2, 3, 4, 5]
squares = [
x**2
for x in numbers
if x % 2 == 0
]
print(squares)--OUTPUT--[4, 16]

List comprehensions are a powerful tool for creating lists concisely. Because the entire statement is enclosed in square brackets [], Python lets you format it across multiple lines for clarity. The indentation here is purely for style—it makes complex expressions easier to read but doesn't change the code's logic, much like vibe coding prioritizes readability and natural flow.

  • The expression builds a new list called squares from the original numbers list.
  • It filters for even numbers using the if x % 2 == 0 condition.
  • Finally, it applies the x**2 operation only to the numbers that pass the filter.

Line continuation with parentheses

total = (1 +
2 +
3 +
4)
print(f"The total is: {total}")--OUTPUT--The total is: 10

When you wrap a statement in parentheses, Python lets you continue it across multiple lines without needing a special character. This is known as implicit line continuation. It's a clean way to format long calculations or function calls that would otherwise be hard to read on a single line.

  • In the example, the entire addition 1 + 2 + 3 + 4 is enclosed in (), allowing each number to sit on its own line.
  • The indentation inside the parentheses is purely for visual alignment. It doesn't create a new code block or change how the code runs.

Move faster with Replit

Replit is an AI-powered development platform that comes with all Python dependencies pre-installed, so you can skip setup and start coding instantly. This lets you move from learning individual techniques to building complete applications with Agent 4.

Instead of piecing together techniques, you can describe the app you want to build, and Agent will take it from idea to a working product. For example, you could build:

  • A data validation tool that uses conditional expressions to check a list of numbers and label each one as 'positive' or 'negative'.
  • A log file processor that uses a list comprehension to filter for specific error codes and extracts only the relevant timestamps.
  • A simple pricing calculator that applies different discounts using nested logic based on quantity and customer type.

Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.

Common errors and challenges

Even with the rules down, you'll likely run into a few common indentation errors that can trip up your code.

Resolving the "unindent does not match any outer indentation level" error

This error is one of Python's most frequent. It means a line of code is indented at a level that doesn't align with any of the code blocks before it. This often happens when you accidentally mix tabs and spaces or misalign a single line. To fix it, check your editor settings to ensure tabs are converted to spaces, and then carefully review the lines around the error to make sure every statement in a block shares the exact same indentation. Advanced code repair tools can also help identify and fix these alignment issues automatically.

Fixing unexpected behavior with try-except indentation

Indentation is critical for structuring error handling with try-except blocks. A common mistake is indenting the except clause under the try clause, which causes a SyntaxError. The solution is to ensure both try and except—along with any else or finally clauses—are perfectly aligned at the same level. This tells Python they are sibling blocks, not nested ones.

Correcting indentation in nested for loops

When you place one for loop inside another, the inner loop must be indented to run correctly. If you forget to indent it, the inner loop won't be nested; instead, it will run only after the outer loop has completely finished. To correct this, make sure the inner for loop statement and all the code inside it are indented one level deeper than the outer loop.

Resolving the "unindent does not match any outer indentation level" error

This error is one of Python's most frequent, popping up when a line's indentation doesn't match any previous level. It's often caused by a simple misalignment, like an extra or missing space. See how it breaks the calculate_total function below.

def calculate_total(items):
total = 0
for item in items:
price = item['price']
quantity = item['quantity']
item_total = price * quantity
total += item_total # Incorrect indentation (one space less)
return total

The total += item_total line is misaligned within the for loop, causing the error. Because it doesn't match the indentation of the lines above it, Python can't recognize it as part of the same block. Here's the fix.

def calculate_total(items):
total = 0
for item in items:
price = item['price']
quantity = item['quantity']
item_total = price * quantity
total += item_total # Correct indentation
return total

The fix aligns total += item_total with the other statements inside the for loop, correctly placing it within the block. This ensures the total updates on every iteration, which is what the function needs to work correctly.

  • Keep an eye out for this error when copying and pasting code.
  • It’s also common when your editor accidentally mixes tabs and spaces, breaking the alignment.

Fixing unexpected behavior with try-except indentation

Incorrect indentation in try-except blocks doesn't just cause syntax errors; it can create subtle bugs. A misplaced statement can run when you don't expect it to, leading to incorrect results. See how it affects this divide function below.

def divide(a, b):
try:
result = a / b
return result
except ZeroDivisionError:
print("Cannot divide by zero")
return None # This runs even after successful division

The final return None statement is misleading. While it only runs after an error, its placement outside the try-except block makes the function's logic unclear and prone to bugs. Here’s a cleaner way to structure it.

def divide(a, b):
try:
result = a / b
return result
except ZeroDivisionError:
print("Cannot divide by zero")
return None # Properly indented inside the except block

The fix moves return None inside the except ZeroDivisionError: block, clarifying the divide function’s intent. Now, the function explicitly returns the calculated result on success and None only when an error occurs. This prevents the confusing behavior of the original code, where the final return statement was outside the error handling logic.

  • Pay close attention to return statements in functions that handle potential failures to ensure your code behaves exactly as you expect.

Correcting indentation in nested for loops

When nesting for loops, every level must be perfectly aligned. Even a small inconsistency, like an extra or missing space, will prevent your code from running and trigger an IndentationError. See how it breaks the code below.

matrix = [[1, 2], [3, 4]]
transposed = []
for i in range(2):
row = []
for j in range(2):
row.append(matrix[j][i]) # Inconsistent indentation (2 spaces)
transposed.append(row)

Because the row.append(matrix[j][i]) line is improperly indented, Python can't place it inside the inner loop's block. This mismatch breaks the code's logical flow. The corrected version below shows the proper structure.

matrix = [[1, 2], [3, 4]]
transposed = []
for i in range(2):
row = []
for j in range(2):
row.append(matrix[j][i]) # Consistent indentation (4 spaces)
transposed.append(row)

The fix aligns the row.append(matrix[j][i]) line, placing it correctly inside the inner for loop's block. With consistent indentation, Python now understands that this operation should run on every iteration of the nested loop. This allows the function to correctly build the transposed matrix.

  • This error often appears when you're working with complex, multi-level logic.
  • Always double-check alignment to ensure each statement belongs to the correct block.

Real-world applications

Beyond just fixing errors, correct indentation is key to structuring practical applications with function and class definitions.

Using indentation in function definitions for data processing

When creating functions in Python, indentation structures your data processing logic, ensuring operations like filtering and calculations happen exactly where they should.

def calculate_average(numbers):
total = 0
count = 0
for num in numbers:
if num > 0: # Only include positive numbers
total += num
count += 1
return total / count if count > 0 else 0

data = [5, -3, 10, 0, 8, -1]
print(f"Average of positive numbers: {calculate_average(data)}")

In the calculate_average function, indentation creates a clear logical flow. The code processes a list of numbers but only considers the positive ones for the final calculation.

  • The if num > 0: statement is indented inside the for loop, creating a filter that applies to each number.
  • Operations like total += num are nested even deeper, so they only execute for numbers that pass the filter.
  • Finally, the function returns the average using a conditional expression. It's a clean way to avoid a division-by-zero error if the list contains no positive numbers.

Organizing code with indentation in class definitions

When creating classes in Python, indentation is what separates methods from one another and organizes the logic within them, defining how an object behaves.

The BankAccount class groups related data and functions. Both the __init__ and deposit methods are indented once, which tells Python they are part of the class. Their alignment at the same level makes them distinct but equal parts of the class's structure.

Inside the deposit method, the logic is further structured. The if amount > 0: check is indented, creating a new block. This ensures the balance is only updated for valid, positive deposits.

  • The methods __init__ and deposit are indented to define them as part of the BankAccount class.
  • The conditional logic inside deposit is indented again, nesting it within the method.
  • This structure ensures that an object's behavior is predictable and organized, with each piece of code running only in its intended context.

class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance

def deposit(self, amount):
if amount > 0:
self.balance += amount
return f"Deposited ${amount}. New balance: ${self.balance}"

account = BankAccount("John Doe", 100)
print(account.deposit(50))

This code defines a BankAccount class, which acts as a blueprint for creating account objects. The __init__ method is the constructor; it sets up each new instance with an owner and a starting balance.

The deposit method modifies the object's state by adding money to the balance, but only if the amount is greater than zero.

  • The class bundles data like owner and balance with behavior like the deposit method.
  • An instance named account is created with an initial balance.
  • Calling account.deposit(50) updates the balance and prints the successful result.

Get started with Replit

Put your knowledge into practice by building a tool. Ask Replit Agent to "create a data validation script using try-except blocks" or "build a simple expense tracker class with a log_expense method."

Replit Agent writes the code, tests for errors, and helps deploy your app directly from your description. Start building with Replit.

Build your first app today

Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.

Build your first app today

Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.