Ditch That if-elif Chain — There’s a Cleaner Way!

There’s a better way to handle conditions — and it makes your code easier to test, extend, and read.

Ditch That if-elif Chain — There’s a Cleaner Way!
Photo by Alex Shu on Unsplash

If your function looks like a staircase of if-elifs, it’s time for an upgrade.

Ditch That if-elif Chain — There’s a Cleaner Way!

We’ve all been there — deep in a project, trying to keep things tidy and readable, when suddenly we’re staring at a mile-long if-elif-else chain that feels more like a staircase to code hell.

def handle_event(event_type): 
    if event_type == "start": 
        start_process() 
    elif event_type == "stop": 
        stop_process() 
    elif event_type == "pause": 
        pause_process() 
    elif event_type == "resume": 
        resume_process() 
    else: 
        print("Unknown event")

It works. But it smells. And as your application grows, so does this branching logic. Add one more condition? The whole thing starts to sag under its own weight.

But here’s the good news: there’s a cleaner, more Pythonic way to write this logic. Let’s explore it.


The Problem with if-elif-else Chains

At first glance, if-elif-else seems like a natural fit. After all, it expresses intent clearly, right?

But as conditions grow, things quickly become:

  • Harder to read: Scanning a dozen conditions isn’t pleasant.
  • Error-prone: Easy to duplicate or miss a condition.
  • Tough to maintain: Adding or modifying behavior later gets messy.

In reality, this kind of logic cries out for abstraction.

Enter: The Function Mapping Pattern

Instead of chaining conditions, why not map event types to handler functions?

Here’s a refactored version of the earlier example:

def start_process(): 
    print("Process started") 
 
def stop_process(): 
    print("Process stopped") 
 
def pause_process(): 
    print("Process paused") 
 
def resume_process(): 
    print("Process resumed") 
 
event_handlers = { 
    "start": start_process, 
    "stop": stop_process, 
    "pause": pause_process, 
    "resume": resume_process, 
} 
 
def handle_event(event_type): 
    handler = event_handlers.get(event_type) 
    if handler: 
        handler() 
    else: 
        print("Unknown event")

Much cleaner, right? Here’s what we gained:

  • Readability: The code reads like a dictionary — because it is one.
  • Maintainability: Adding a new handler is as simple as adding a new key-value pair.
  • Separation of concerns: Logic lives where it belongs — in the functions themselves.

When This Pattern Shines

This approach is especially useful when:

  • You’re dealing with discrete conditions (like commands or states).
  • Each condition maps to a distinct action.
  • You want to make your codebase more extensible.

You’ll see this used often in:

  • Command-line tools (dispatching commands).
  • State machines.
  • REST APIs (routing HTTP methods or actions).
  • Game development (handling user inputs or state transitions).

Bonus: Default Behaviors and Fallbacks

What if you want to have a default handler when the event type isn’t found?

Just use .get() with a fallback:

def unknown_event(): 
    print("Unknown event type!") 
 
def handle_event(event_type): 
    handler = event_handlers.get(event_type, unknown_event) 
    handler()

Simple. Elegant. No else clause needed.


And for the Fancy Folks: Using @dataclass and Enum

Want to take it a step further for robustness? Use an Enum for event types:

from enum import Enum, auto 
 
class EventType(Enum): 
    START = auto() 
    STOP = auto() 
    PAUSE = auto() 
    RESUME = auto()

Then use these enum values as dictionary keys, which gives you better type safety and autocompletion in IDEs.


If your if-elif-else chain feels bloated, it probably is.
Replace it with a function mapping and breathe fresh air into your codebase.

Remember: Code should be easy to read, easy to extend, and hard to break.


Bonus Tip

You can apply this pattern to not just functions, but classes, lambda expressions, or even partial functions for preconfigured behaviors.


Final Thoughts

Clean code is more than just pretty formatting — it’s about reducing complexity and improving clarity. Refactoring if-elif chains into mappings is a small change that can have a big impact.

Next time you’re tempted to write that fifth elif, pause and ask yourself:

“Could this be a dictionary instead?”

Chances are, it can.
And your future self will thank you.


Enjoyed this post?
- Leave a comment — Have you used this pattern before?
- Share it with your Python buddies.
- Follow for more clean code tips and real-world dev wisdom.

Photo by Nadia Rudenko on Unsplash