Python List Comprehension if/else: 6 Working Examples

Quick answer: Use [expression for item in iterable if condition] when the condition decides whether an item belongs in the result. Use [value_if_true if condition else value_if_false for item in iterable] when every input item should produce one of two values. The location of if changes its job.

A Python list comprehension with if or if-else can transform, filter, or classify values while building a new list. The syntax is compact, but it becomes much easier to remember once you separate two ideas: a conditional expression chooses a value, while a trailing if filters an item out.

This guide focuses on that distinction. It covers the valid forms, evaluation order, multiple conditions, filtering and replacement in the same comprehension, nested loops, common syntax errors, scope, memory use, and the point where a normal loop is clearer. All six examples below were executed with Python rather than treated as untested fragments.

The language rules come from the official Python list comprehension tutorial and the Python expression reference. Python defines a comprehension as one expression followed by at least one for clause and then zero or more for or if clauses. That definition explains why an else belongs in the first expression, before for.

List Comprehension if vs if-else Syntax

Goal Syntax Result length
Transform every item [expression for item in iterable] Same as the input
Keep matching items [expression for item in iterable if condition] Same or shorter
Choose between two values [true_value if condition else false_value for item in iterable] Same as the input
Choose a value, then filter [true_value if condition else false_value for item in iterable if filter_condition] Same or shorter

The first if in the last form belongs to the conditional expression. It must have an else because the expression has to return a value. The final if belongs to the comprehension and has no else; a false result means the current item is skipped.

Three valid patterns: filter with a trailing if, choose with a leading if-else, or combine both decisions.

Use a Trailing if to Filter Items

Put if after the iterable when you only want items that pass a test. Python loops through the source from left to right, checks the filter, and evaluates the output expression only for items that pass. This is useful for selecting valid records, removing empty text, keeping values in a range, or taking even numbers.

numbers = range(1, 11)
even_squares = [
    number ** 2
    for number in numbers
    if number % 2 == 0
]

print(even_squares)

Output: [4, 16, 36, 64, 100]

The condition does not add False or a placeholder for odd values. It prevents those values from reaching the result at all. That is why this list has five items instead of ten.

This pattern is the direct comprehension equivalent of a loop containing an if and an append(). For a wider comparison of iteration patterns, see how to iterate through a Python list. If the main purpose is lazy filtering rather than producing a list immediately, compare it with Python filter() and lambda.

Use if-else Before for to Choose a Value

A conditional expression has the form x if condition else y. It evaluates the condition first, then evaluates only the selected branch. In a comprehension, that whole expression occupies the value position before for.

temperatures = [-4, 0, 7, 15]
labels = [
    "freezing" if temperature <= 0 else "above freezing"
    for temperature in temperatures
]

print(labels)

Output: ['freezing', 'freezing', 'above freezing', 'above freezing']

Every temperature produces one label, so the output has the same length as the input. This form transforms or classifies; it does not remove anything. PythonPool’s conditional expression guide explains the same x if condition else y expression in assignments, returns, and other contexts. Here, the expression is specifically the value emitted by a list comprehension.

Combine if-else With a Filter

You can use both forms when they answer different questions. First decide whether an item is valid enough to keep. Then decide which value the kept item should produce. Reading the comprehension from the for clause often makes that order easier to see.

scores = [95, 72, -1, 68, 140, 81]
results = [
    "pass" if score >= 70 else "review"
    for score in scores
    if 0 <= score <= 100
]

print(results)

Output: ['pass', 'pass', 'review', 'pass']

The trailing test rejects -1 and 140 because they are outside the accepted score range. The leading conditional expression then labels each valid score. Combining the two is readable here because the filter and classification are short and independent.

Do not force unrelated business rules into one line. If validation needs error messages, logging, several branches, or shared intermediate results, a regular loop or helper function will be easier to test.

A trailing filter rejects an item before the leading expression produces a value for the new list.

How Python Evaluates the Comprehension

For a single-loop comprehension, the practical sequence is:

  1. Obtain the next item from the iterable.
  2. Evaluate each trailing filter from left to right.
  3. Skip the item immediately if a filter is false.
  4. Evaluate the leading expression. If it is conditional, evaluate its condition and only the chosen branch.
  5. Append the resulting value to the new list.

The expression reference describes additional for and if clauses as nested blocks from left to right. This is the reliable way to expand a difficult comprehension into a loop: preserve the written order of every for and trailing if, then append the leading expression at the innermost point.

Use Multiple Conditions Without Hiding the Rule

A filter can use and, or, not, comparisons, membership tests, and method calls. Keep the condition close to the language of the requirement. A short named helper is often better than repeating a complicated predicate.

users = [
    {"name": "Ada", "active": True, "email": "[email protected]"},
    {"name": "Lin", "active": False, "email": "[email protected]"},
    {"name": "Sam", "active": True, "email": ""},
    {"name": "Maya", "active": True, "email": "[email protected]"},
]

active_emails = [
    user["email"].lower()
    for user in users
    if user["active"] and user.get("email")
]

print(active_emails)

Output: ['[email protected]', '[email protected]']

The filter first checks the active flag. Because and short-circuits, Python only needs the email test when the first condition is true. The expression then normalizes the address. If the condition starts to need several dictionary lookups or exceptions, move it into a function with a descriptive name.

Multiple for Clauses and Nested Data

Additional for clauses behave like nested loops. Their order matters. The first for is the outer loop, the next for is inside it, and a following if filters at that point.

matrix = [
    [0, 4, 0],
    [7, 0, 9],
]

nonzero_cells = [
    (row_index, column_index, value)
    for row_index, row in enumerate(matrix)
    for column_index, value in enumerate(row)
    if value != 0
]

print(nonzero_cells)

Output: [(0, 1, 4), (1, 0, 7), (1, 2, 9)]

This is compact because the operation is still one clear transformation: keep nonzero cells and record their coordinates. When working with rows and columns more broadly, the Python 2D list guide covers independent rows, indexing, copying, flattening, and sorting nested lists.

A nested comprehension is different from merely having two for clauses. For example, a leading expression such as [value for value in row] creates one inner list per outer item. The official tutorial notes that the initial expression can itself be another list comprehension. Use that form only when the nested result is genuinely the intended data shape.

Common Syntax Errors and Why They Happen

Putting else After the for Clause

[value for value in items if condition else other] is invalid. A trailing comprehension filter does not accept else. Move the full conditional expression to the front: [value if condition else other for value in items].

Expecting a Filter to Insert a Fallback

[value for value in items if condition] skips false cases. It never inserts None, zero, or another fallback. Use a leading if-else expression when positions and output length must be preserved.

Confusing if-else With elif

Python has no elif keyword inside a conditional expression. Multiple choices require nested conditional expressions, such as "high" if score >= 90 else "pass" if score >= 70 else "review". That is valid, but more than two or three short branches usually reads better in a helper function.

Doing Work for Side Effects

Do not use a comprehension only to call print(), append to another list, write files, or mutate external state. A comprehension communicates that a new collection is the result. A normal for loop communicates repeated actions.

When a Normal Loop Is Better

The shortest code is not automatically the clearest code. Keep a comprehension when a reader can identify the output expression, iteration, and filter without mentally executing several branches. Use a helper or a regular loop when the logic needs explanation.

orders = [
    {"id": 101, "total": 80, "cancelled": False, "priority": True},
    {"id": 102, "total": 0, "cancelled": False, "priority": False},
    {"id": 103, "total": 45, "cancelled": True, "priority": False},
    {"id": 104, "total": 30, "cancelled": False, "priority": False},
]

def shipping_label(order):
    if order["cancelled"]:
        return "cancelled"
    if order["priority"] or order["total"] >= 75:
        return "priority"
    return "standard"

labels = [shipping_label(order) for order in orders if order["total"] > 0]
print(labels)

Output: ['priority', 'cancelled', 'standard']

The comprehension remains simple: ignore zero-total records and map the others through a named rule. The branching lives in a function where each outcome can be tested directly. This is usually more maintainable than nesting two conditional expressions around several dictionary lookups.

Choose a comprehension for a clear collection transform, a generator for one-pass data, and a loop or helper for branching and side effects.

List Comprehension vs Generator Expression

Square brackets build the entire list immediately. Parentheses create a generator expression that yields values as they are requested. The syntax inside is nearly the same, including filters and conditional expressions, but the result and evaluation timing differ.

Use a list when you need indexing, repeated iteration, a known length, or a concrete result to return. Use a generator for a one-pass pipeline or a large input when the next consumer can process values lazily. Python’s expression reference states that a generator expression yields the same values as the corresponding list comprehension, while most of its work is deferred until iteration. The historical details are documented in PEP 289.

The Python MemoryError guide shows why avoiding a large temporary list can matter. Do not replace every list with a generator, though. Laziness changes when errors occur and a generator is normally consumed once.

Scope and Performance Notes

In modern Python, the comprehension’s loop target does not overwrite a same-named value in the surrounding scope. The language reference describes comprehension execution using an implicitly nested scope, apart from evaluation of the leftmost iterable. This fixes the loop-target leakage associated with old Python 2 list comprehensions.

CPython 3.12 implemented PEP 709, which inlines list, set, and dictionary comprehensions as an implementation optimization while preserving the expected isolation of iteration names. That can reduce comprehension overhead, but it is not a reason to write unreadable code. Runtime cost is usually dominated by the work inside the expression, the number of items, allocations, and any function or I/O calls.

A comprehension is often faster than an equivalent hand-written append loop in CPython, but avoid universal performance claims. Benchmark the real operation with representative data. Choose the form that makes the data transformation easiest to verify, then optimize a measured bottleneck.

Choosing the Right Pattern

  • Use a trailing if when false cases should disappear.
  • Use a leading if-else when every input should produce a value.
  • Use both when validation and classification are separate, short decisions.
  • Use multiple for clauses only when their nested-loop order is obvious.
  • Use a helper function for branching that deserves a name or independent tests.
  • Use a normal loop for side effects, early exits, exception handling, or stateful work.
  • Use a generator expression when the result can be consumed once and building a full list would waste memory.

Related collection patterns include Python map(), set comprehensions, and Python for-each style iteration. Each tool has a different signal: a comprehension builds a collection, map() applies a callable lazily, a set comprehension enforces uniqueness, and a loop is best when the work is primarily procedural.

How to Test a Conditional Comprehension

Test the boundary that changes each condition, not only a typical value. For an even-number filter, include odd and even inputs. For a pass threshold of 70, test 69, 70, and 71. For a validation filter, include the smallest and largest accepted values plus values just outside the range. Also test an empty iterable; a well-formed comprehension normally returns an empty list without special handling.

When a comprehension combines filtering and if-else, verify two properties separately. First, assert which source items survive the filter. Second, assert the value produced for each surviving item. This catches a common regression where a comparison is moved from the trailing filter into the conditional expression, silently preserving items that should have disappeared.

If the expression calls a helper, test that helper directly with one case per branch. Then keep one integration test for the final list order and length. These focused checks make a future readability refactor safe: the implementation can move between a comprehension and a loop without changing the behavior callers depend on.

Frequently Asked Questions

Can a Python list comprehension contain if and else?

Yes. Put the conditional expression before for: [x if condition else y for item in iterable]. This produces one value for every input item.

Why does else come before for in a list comprehension?

Because x if condition else y is the single value-producing expression required at the start of the comprehension. A trailing if is a filter clause and has no else.

Can I use if-else and a filter in the same comprehension?

Yes. Use [x if choice else y for item in iterable if keep]. The trailing filter first determines whether the item is kept, and the leading conditional expression chooses its output value.

Can a list comprehension have multiple conditions?

Yes. Combine short tests with and, or, not, or multiple trailing if clauses. Move a complicated rule into a named helper function.

Does a list comprehension change the original list?

No. It creates a new list. Objects referenced by the source can still be mutable, but filtering or transforming through a comprehension does not replace the source list itself.

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted