Python - if, else, elif conditions

Python if-elif-else: How AI API Routing and Token Logic Actually Work

Every beginner tutorial uses student grades or age checks. But if you are building web apps, chatbots, or modern SaaS tools today, your conditional logic looks very different.

Imagine you are building an AI Chat Gateway for an app. A user types a prompt, and before sending it off to an expensive LLM, your backend has to make a split-second routing decision based on token length and user tier:

  • Over 4,000 tokens: Route to an Ultra/Long-Context Model (highest compute).
  • Over 1,000 tokens: Route to a Pro Model (balanced).
  • Up to 1,000 tokens: Route to a Fast/Flash Model (low latency, cheap).
  • 0 or negative tokens: Reject immediately (invalid request).

Code executes line by line from top to bottom. To branch into different execution paths—run this pipeline or fall back to that one—Python uses if, elif, and else.

Conditional routing is foundational to production engineering. Read more on how modern backends leverage these patterns in our guide on the role of Python in AI and data science.


Step 1: The First Check (if)

Start with a single rule: check if the incoming prompt exceeds our heavy-compute threshold.

prompt_tokens = 4850

if prompt_tokens > 4000:
    print("Routing to: Long-Context Model")

Under the hood:

  1. Python checks prompt_tokens > 4000.
  2. That comparison resolves to True or False.
  3. Because 4850 > 4000 is True, Python steps inside the indented block and runs the code.

If prompt_tokens was 850, the condition would evaluate to False, Python would ignore the indented block entirely, and move on.

Scope rule: In Python, indentations (4 spaces) aren't visual decoration—they tell the interpreter exactly where the condition's block begins and ends.


Step 2: The Fallback Pipeline (else)

What if we only had two modes: heavy-compute model, or the standard default model?

Writing two standalone if checks is inefficient:

prompt_tokens = 450

if prompt_tokens > 1000:
    print("Routing to: Pro Model")
if prompt_tokens <= 1000:
    print("Routing to: Standard Flash Model")

Both conditions run independently. If the first check is True, Python still wastes clock cycles checking the second one, even though a request cannot be both above and below 1,000 tokens.

Use else to catch everything that doesn't trigger the first condition:

prompt_tokens = 450

if prompt_tokens > 1000:
    print("Routing to: Pro Model")
else:
    print("Routing to: Standard Flash Model")

Notice that else takes no condition. It is a pure catch-all: if the initial if evaluates to False, execution jumps directly to else.

If you only need a compact, one-line decision for simple assignments, see our quick guide on the Python ternary operator.


Step 3: Multi-Tier Routing (elif)

In production, you rarely have just two outcomes. You have multiple model sizes and edge cases.

Chaining independent if statements creates subtle, catastrophic bugs:

# The naive approach: DO NOT DO THIS
prompt_tokens = 4500

if prompt_tokens > 0:
    print("Routing to: Standard Flash Model")
if prompt_tokens > 1000:
    print("Routing to: Pro Model")
if prompt_tokens > 4000:
    print("Routing to: Long-Context Model")

Output:

Routing to: Standard Flash Model
Routing to: Pro Model
Routing to: Long-Context Model

Because 4,500 is greater than 0, greater than 1,000, and greater than 4,000, every single independent block runs. Your server just sent three separate API requests for one prompt.

To chain checks so that only one branch executes, use elif (short for "else if"):

prompt_tokens = 2200

if prompt_tokens > 4000:
    print("Routing to: Long-Context Model")
elif prompt_tokens > 1000:
    print("Routing to: Pro Model")
elif prompt_tokens > 0:
    print("Routing to: Standard Flash Model")
else:
    print("Error: Empty or invalid payload")

Python checks from top to bottom. As soon as one condition evaluates to True:

  1. It runs that block.
  2. It exits the entire structure immediately, skipping every remaining elif and the else.

For prompt_tokens = 2200:

  • 2200 > 4000 is False → Moves to next branch.
  • 2200 > 1000 is True → Prints "Routing to: Pro Model" and stops checking.

The Order Trap: Shadowed Conditions

Look at what happens if we accidentally invert the order of these checks:

prompt_tokens = 4500

# BUG: Broader condition placed first
if prompt_tokens > 0:
    print("Routing to: Standard Flash Model")
elif prompt_tokens > 1000:
    print("Routing to: Pro Model")
elif prompt_tokens > 4000:
    print("Routing to: Long-Context Model")
else:
    print("Error: Empty payload")

Input: 4500 tokens.
Expected: Long-Context Model.
Actual output:

Routing to: Standard Flash Model

Why it broke:
Because 4500 > 0 is true right away, Python executes that block and bails out. The downstream checks for 1000 and 4000 are completely shadowed and will never run for any positive number.

The rule: When working with numerical ranges using > or >=, place the most restrictive (highest threshold) condition at the top, stepping down toward broader checks.


Real-World Pattern: Nested Decision Trees

AI apps often gate expensive operations by user subscription tier before allocating heavy resources.

Let's nest our model routing logic inside a rate-limit and quota verification check:

prompt_tokens = 5200
has_active_subscription = True
daily_quota_used = 85  # percentage

if has_active_subscription and daily_quota_used < 100:
    # Outer check passed: determine model pipeline
    if prompt_tokens > 4000:
        print("Status: 200 | Pipeline: Ultra Long-Context Engine")
    elif prompt_tokens > 1000:
        print("Status: 200 | Pipeline: Balanced Pro Engine")
    elif prompt_tokens > 0:
        print("Status: 200 | Pipeline: Fast Flash Engine")
    else:
        print("Status: 400 | Bad Request: Token count cannot be zero")
else:
    # Outer check failed: block heavy execution immediately
    print("Status: 429 | Quota Exceeded or Subscription Expired")

If has_active_subscription is False, Python skips the entire token-routing tree and drops straight into the outer else block, saving compute cycles.

Clean code tip: Avoid nesting more than two layers deep. If you find yourself indenting 3 or 4 times, extract the inner branches into helper functions or use guard clauses (early returns). When working inside loops, you can also control execution flow using Python break and continue statements.


When NOT to Use elif Chains

Long ladders of elif statements are fine for ranges (>, <), but they turn messy and slow when matching exact values or operational commands.

1. The Dictionary Dispatch (O(1) Exact Lookup)

When picking models by name:

# Clunky and repetitive
def get_model_endpoint(model_name):
    if model_name == "flash":
        return "https://api.gateway/v1/flash"
    elif model_name == "pro":
        return "https://api.gateway/v1/pro"
    elif model_name == "long-context":
        return "https://api.gateway/v1/ultra"
    else:
        return "https://api.gateway/v1/fallback"

Replace it with a dictionary lookup:

# Direct hash map dispatch
def get_model_endpoint(model_name):
    endpoints = {
        "flash": "https://api.gateway/v1/flash",
        "pro": "https://api.gateway/v1/pro",
        "long-context": "https://api.gateway/v1/ultra",
    }
    return endpoints.get(model_name, "https://api.gateway/v1/fallback")

2. Structural Pattern Matching (match-case)

For handling API response status codes or intent types in Python 3.10+:

response_code = 429

match response_code:
    case 200:
        print("Model inference complete.")
    case 400:
        print("Malformed prompt payload.")
    case 429:
        print("Rate limit reached. Retrying with exponential backoff...")
    case 503:
        print("GPU cluster capacity unavailable.")
    case _:
        print("Unknown error occurred.")

The wildcard case _: serves the exact same role as else, ensuring unhandled states are never dropped.


Quick Reference

Keyword Role Execution Timing
if Initial evaluation Always evaluated first.
elif Intermediate checks Evaluated sequentially only if prior checks return False.
else Fallback branch Executes only when every preceding condition evaluated to False.

Conditional branching is the core infrastructure behind intelligent pipelines—filter broad issues early, structure your constraints from narrow to wide, and use dictionaries or pattern matching when handling static exact matches.

Ready to level up? Learn how to automate tasks with loops in our tutorial on Python for loops with examples, or practice building apps with our collection of simple Python projects with source code.

Post a Comment

Previous Post Next Post