DEV Community

Cover image for Python by Structure: The For/Else Block You Didn't Know Existed
Aaron Rose
Aaron Rose

Posted on

Python by Structure: The For/Else Block You Didn't Know Existed

"Margaret," Timothy said, looking up from his code, "I learned about try/else from you yesterday. But I just saw else after a for loop. That can't be right, can it?"

Margaret smiled. "Python has a fondness for the else clause. It appears in more places than most developers realize. Let me show you why for/else exists and when it's useful."

Timothy pulled up the code he'd been reading - a function to find a user by ID:

def find_user(user_id, users):
    found = False
    result = None

    for user in users:
        if user['id'] == user_id:
            found = True
            result = user
            break

    if not found:
        print(f"User {user_id} not found")
        return None

    return result
Enter fullscreen mode Exit fullscreen mode

"See all these extra variables?" Timothy pointed at found and the separate check afterward. "It feels clunky. There must be a better way."

The Problem: Flag Variables Everywhere

"There is," Margaret said. "The else clause on loops solves exactly this problem. Watch."

She rewrote the function:

def find_user(user_id, users):
    for user in users:
        if user['id'] == user_id:
            return user
    else:
        print(f"User {user_id} not found")
        return None
Enter fullscreen mode Exit fullscreen mode

"Wait," Timothy frowned. "That else is attached to the for loop, not the if statement?"

"Exactly. Let me show you the structure."

Tree View:

find_user(user_id, users)
    For user in users
        If user['id'] == user_id
            Return user
    Else
        print(f'User {user_id} not found')
        Return None
Enter fullscreen mode Exit fullscreen mode

English View:

Function find_user(user_id, users):
  For each user in users:
    If user['id'] == user_id:
      Return user.
  Else:
    Evaluate print(f'User {user_id} not found').
    Return None.
Enter fullscreen mode Exit fullscreen mode

Timothy studied the structure carefully. "The else sits at the same level as the for loop... So it runs when the loop finishes?"

"Almost," Margaret said. "It runs when the loop finishes naturally - without hitting a break or return. If you find what you're looking for and exit early, the else never runs."

"Oh!" Timothy's eyes widened. "So else here means 'if we searched everything and found nothing.'"

"Precisely. The structure shows it clearly - the else is part of the loop's control flow, not part of the if statement inside."

Understanding the Pattern

Margaret pulled out another example to drive the point home:

def validate_all_positive(numbers):
    for num in numbers:
        if num <= 0:
            print(f"Found invalid number: {num}")
            return False
    else:
        print("All numbers are positive!")
        return True
Enter fullscreen mode Exit fullscreen mode

Tree View:

validate_all_positive(numbers)
    For num in numbers
        If num <= 0
            print(f'Found invalid number: {num}')
            Return False
    Else
        print('All numbers are positive!')
        Return True
Enter fullscreen mode Exit fullscreen mode

English View:

Function validate_all_positive(numbers):
  For each num in numbers:
    If num <= 0:
      Evaluate print(f'Found invalid number: {num}').
      Return False.
  Else:
    Evaluate print('All numbers are positive!').
    Return True.
Enter fullscreen mode Exit fullscreen mode

"Now I see it," Timothy said. "The else block is the 'success case' - it only runs if we checked every number without finding a problem."

"That's the pattern," Margaret confirmed. "Search loops benefit most from for/else. Without it, you need flag variables like your found boolean. With it, the structure expresses your intent directly: 'loop through these items, and if we never exit early, do this.'"

Timothy looked back at his original code with the flag variable. "So all those found = False and if not found: checks are just working around not knowing about for/else?"

"Most of them, yes. Python gives you the structural tool to express 'search succeeded' versus 'search failed' without extra variables cluttering your logic."

"Does this work with while loops too?" Timothy asked.

"It does. Any loop in Python can have an else clause. Same rule applies - it runs only if the loop completes without break or return."

Timothy saved his refactored function, already thinking about other search loops in his codebase. "First try/else, now for/else. What other else clauses is Python hiding?"

Margaret laughed. "Those are the main ones. Python's consistent here - else always means 'if the primary path didn't exit early.' Whether that's 'no exception raised' or 'loop completed naturally,' the principle is the same."

"The structure is the logic underneath," Timothy repeated Margaret's phrase from yesterday. "Once you see the pattern, it shows up everywhere."

"Now you're learning to think structurally," Margaret said, returning to her desk with a satisfied smile.


Explore Python structure yourself: Download the Python Structure Viewer - a free tool that shows code structure in tree and plain English views. Works offline, no installation required.

Python Structure Viewer


Aaron Rose is a software engineer and technology writer at tech-reader.blog and the author of Think Like a Genius.

Top comments (5)

Collapse
 
xwero profile image
david duymelinck • Edited

I know Python has a rule to make everything explicit. But if you have a return on the loop, why do you need an else?

def validate_all_positive(numbers):
    for num in numbers:
        if num <= 0:
            print(f"Found invalid number: {num}")
            return False

     print("All numbers are positive!")
     return True
Enter fullscreen mode Exit fullscreen mode

This makes the function structure flatter.

The sentence in English is; look for a number in numbers that is smaller or equal to zero and return false. When false isn't returned, return true.

Collapse
 
aaron_rose_0787cc8b4775a0 profile image
Aaron Rose

Hi David, You're absolutely right! That example doesn't need the else - a simple return after the loop works better and is clearer.
for/else shines more in cases like searching where you need to handle "never found it" versus "found it and returned early."
Thanks for the feedback - always appreciate folks keeping the examples sharp!
Cheers buddy ❤

Collapse
 
heintingla profile image
Willie Harris

Great article! It really clarifies how the else clause on a loop isn’t about “if this failed,” but rather “if the loop ran all the way through without a break.” It’s a much cleaner, more Pythonic way to express that you didn’t find what you were looking for — without extra flag variables.

Collapse
 
aaron_rose_0787cc8b4775a0 profile image
Aaron Rose

You're absolutely right, Willie - that's exactly it! The else on a loop isn't about "if this failed," it's about "if the loop ran all the way through without a break."

That's a really sharp way to articulate it. Thanks for adding that clarity!

Cheers buddy ❤️

Collapse
 
growthandchangecounseling profile image
Growth and Change Counseling

Like this App!