The Health Check: How a Simple Dictionary Filter Reveals Your Engineering Mindset

Junior/Mid Engineer Asked at: All of them. This is a fundamental skill.

Q: Given a dictionary of services and their status, write Python code to print only the services that are "DOWN".

Why this matters: This is a test of fluency. The interviewer isn't checking if you can write a loop. They're checking if you can think in Python. Your answer reveals whether you write code that is merely correct, or code that is clear, concise, and idiomatic—the hallmarks of a professional.

Interview frequency: Very high. A staple "can you code?" question.

❌ The Death Trap

The trap isn't writing incorrect code, but writing clumsy code. The candidate writes a verbose loop that works but feels like it was translated from another language (like C or Java). It gets the job done, but it misses the soul of Python.

"The merely correct, but uninspired, answer:"

services = {'api': 'UP', 'database': 'DOWN', 'cache': 'UP'}
down_services = []
for key in services.keys():
    if services[key] == 'DOWN':
        down_services.append(key)

for service in down_services:
    print(service)

This works, but it's not fluent. Iterating over `keys()` just to do a lookup inside the loop (`services[key]`) is inefficient and verbose. It shows a lack of familiarity with more direct ways to iterate and filter in Python.

🔄 The Reframe

What they're really asking: "Can you express your intent directly? Show me you can write code that declares *what* you want, not just the step-by-step instructions for *how* to get it."

This reveals your relationship with the language. Do you see it as a set of tools to be assembled, or as a medium for expressing ideas? The Pythonic way values clarity and conciseness, which leads to more readable and maintainable code.

🧠 The Mental Model

I separate this into two styles of thinking: **The Recipe vs. The Request.**

1. The Recipe (Imperative): You provide a detailed, step-by-step list of instructions. "First, get an empty bowl. For every item in the pantry, check its label. If the label says 'sugar', put it in the bowl. When you are done, show me the bowl." This is the verbose `for` loop.
2. The Request (Declarative): You state your desired outcome clearly. "Bring me all the items from the pantry that are labeled 'sugar'." This is the list comprehension. It expresses *what* you want, trusting the system to handle the *how*.

📖 The War Story

Situation: "I was reviewing a pull request for a new SRE dashboard. Part of the code was responsible for pulling a large JSON object of system metrics and generating different lists for different UI components: high-CPU pods, low-memory nodes, services with high error rates, etc."

Challenge: "The code was a 50-line monstrosity of nested `for` loops and `if` statements. Each filter had its own verbose loop, creating an empty list, appending to it, and so on. It was incredibly difficult to tell at a glance what the business logic for each filter was."

Stakes: "The code was fragile. Adding a new filter for 'DEGRADED' services meant carefully inserting another multi-line block into this tangled mess, with a high risk of introducing a bug. The cognitive overhead was huge. It was a failure of expression, not of logic."

✅ The Answer

"Of course. I would first show the straightforward, readable approach with a standard loop, and then demonstrate the more concise and Pythonic way using a comprehension. Both are correct, but one expresses the intent more directly."

The Input Data

service_statuses = {
    'api-gateway': 'UP',
    'user-database': 'DOWN',
    'redis-cache': 'UP',
    'payment-processor': 'DEGRADED',
    'auth-service': 'DOWN'
}

Option 1: The Clear `for` Loop (The Recipe)

This approach is perfectly fine, especially for beginners. It's explicit and easy to follow.

print("--- Using a for loop ---")
for service, status in service_statuses.items():
    if status == 'DOWN':
        print(service)

This is a big improvement over the `keys()` version because `.items()` efficiently gives us both the key and value in each iteration without a second lookup.

Option 2: The Pythonic Comprehension (The Request)

This is the fluent, idiomatic way. It collapses the entire loop and condition into a single, highly readable expression.

print("\n--- Using a list comprehension ---")
down_services = [service for service, status in service_statuses.items() if status == 'DOWN']

for service in down_services:
    print(service)

This code reads almost like an English sentence: "Create a list of `service` for each `service, status` pair, but only if the `status` is 'DOWN'." This is the declarative style that Python excels at.

🎯 The Memorable Hook

This connects the choice of a comprehension directly to the principle of clear communication with future readers of your code (including your future self). It shows you're optimizing for clarity, not just for the interpreter.

💭 Inevitable Follow-ups

Q: "How would you find all services that are NOT 'UP'?"

Be ready: "I'd just change the condition in the comprehension: `if status != 'UP'`. This would catch both 'DOWN' and 'DEGRADED' statuses, which is often what you want for an alerting system."

Q: "What if the dictionary was massive, with millions of services, and you only needed to process the down services one at a time without storing them all in a new list?"

Be ready: "For that, I'd use a generator expression. By changing the square brackets `[]` to parentheses `()`, Python creates a generator object instead of a list. It yields one result at a time, making it incredibly memory-efficient for large datasets. For example: `down_service_gen = (service for service, status in ...)`."

🔄 Adapt This Framework

If you're junior: The clear `for` loop using `.items()` is a great, solid answer. Presenting the comprehension as an alternative shows you're learning and thinking about Pythonic style.

If you're senior: You should lead with the list comprehension as the default, correct answer for this task. You should be able to explain *why* it's preferred (clarity, conciseness, performance) and proactively bring up generator expressions as the solution for memory-constrained scenarios.

Written by Benito J D