Skip to Content
Course content

464: Writing Pythonic Loops and Comprehensions

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've spent a lot of time reviewing code for junior developers, and there is one pattern that pops up constantly: the obsession with "one-liners." There's a common belief that because list comprehensions exist, using a standard for loop is somehow "un-Pythonic" or "amateur."

The Myth: "Comprehensions are always better than loops"

Let's look at a piece of code where someone tried to be too clever. Imagine we have a list of user IDs, and we need to log each one to a database.

# The "Clever" way (Avoid this!)
[log_user_to_db(user_id) for user_id in user_ids]

Technically, this works. But it's fundamentally wrong. Why? Because a list comprehension is designed to create a new list. In the example above, the developer isn't interested in the list that gets created; they just want the side effect of the log_user_to_db function. Python actually allocates memory for a list of None values (since the function likely returns nothing) and then immediately throws that list away. It's wasteful and confusing to anyone reading the code.

The Correction: Using the right tool for the intent

If your goal is to do something (a side effect), use a for loop. If your goal is to build something, use a comprehension. It's a simple distinction, but it's what separates a script that just works from a professional codebase.

Here is the Pythonic way to handle the same task:

# The Pythonic way
for user_id in user_ids:
    log_user_to_db(user_id)

Now, let's look at where comprehensions actually shine. Suppose you have a list of raw temperature readings in Celsius, but you only want the Fahrenheit values for readings that are above freezing (0°C).

celsius_readings = [12, -5, 22, 0, -1, 18]

# The clunky way
fahrenheit_above_freezing = []
for temp in celsius_readings:
    if temp > 0:
        f = (temp * 9/5) + 32
        fahrenheit_above_freezing.append(f)

That's five lines of boilerplate to do one simple transformation. In Python, we can collapse this into a single, readable line that describes what is happening rather than how to append to a list:

# The Pythonic way
fahrenheit_above_freezing = [(temp * 9/5) + 32 for temp in celsius_readings if temp > 0]

Stop before you hit the "Readability Wall"

I want to give you a warning: just because you can nest comprehensions doesn't mean you should. I once encountered a project where a developer nested three list comprehensions to flatten a matrix and filter values. It looked like a puzzle from a cryptography textbook.

My rule of thumb is this: if your comprehension spans more than two lines or has more than two for or if clauses, break it back out into a standard loop. Your future self—and your teammates—will thank you. Python is meant to be read like English; when it starts looking like alphabet soup, you've gone too far.




📋 Practical Task

Refactoring the Sensor Data Pipeline

You've been handed a legacy script that processes a list of sensor dictionaries. The current code is using an inefficient loop to filter and transform data. Your task is to refactor this into a clean, Pythonic list comprehension.

The Goal: Create a list of "active" sensor names (strings) but only for sensors that have a status of "online" and a reading greater than 50.

sensors = [
    {"name": "Sensor_A", "status": "online", "reading": 62},
    {"name": "Sensor_B", "status": "offline", "reading": 85},
    {"name": "Sensor_C", "status": "online", "reading": 41},
    {"name": "Sensor_D", "status": "online", "reading": 94},
    {"name": "Sensor_E", "status": "offline", "reading": 12},
]

# REFACTOR THIS:
active_high_sensors = []
for s in sensors:
    if s["status"] == "online":
        if s["reading"] > 50:
            active_high_sensors.append(s["name"])

print(active_high_sensors) 
# Expected Output: ['Sensor_A', 'Sensor_D']

Rewrite the active_high_sensors logic using a single list comprehension. Ensure you are only extracting the "name" value.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.