List Comprehensions in Python

Master Python list comprehensions to create, filter, and transform lists in a single line. Learn the syntax, common patterns, and when to use a regular loop instead.

5 min read

A list comprehension is a Python syntax that builds a new list from an existing iterable in a single line of code. If you have ever written a loop that creates an empty list and then calls append on every iteration, a list comprehension replaces those three or four lines with one expression that reads almost like a sentence. The result is the same list you would have built with the loop, but the code is shorter, runs faster because it skips the repeated lookup and function call overhead of calling append on every iteration, and communicates your intent more directly to anyone reading the code.

The comprehension is not a different kind of list. It produces a regular Python list that you can index, slice, sort, and pass to any function that expects a list. The comprehension is purely a creation syntax, a more concise way to call the list constructor with a pattern. Once the list exists, it behaves exactly like any list created with square brackets or the list constructor. If you have not yet read about creating and accessing Python lists, that article covers the fundamental list operations that comprehensions produce.

The basic comprehension pattern

A list comprehension sits inside square brackets and has three parts: an expression that produces each element, a for clause that defines the source of items, and an optional if clause that filters which items are included. The simplest form has just an expression and a for clause.

pythonpython
squares = [x ** 2 for x in range(10)]

This single line creates the list [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]. The equivalent loop would be four lines: create an empty list, write a for statement, append each squared value inside the loop body, and then the list variable holds the result. The comprehension does the same work but keeps the focus on what you are building rather than on the mechanics of how you build it.

The expression can be any valid Python expression that produces a value. You can call functions, perform arithmetic, combine strings, or create tuples. The for clause can iterate over any iterable, including lists, strings, ranges, file objects, and the results of other functions. This generality means you can use comprehensions for data transformation, type conversion, method application, and any scenario where you need a new list whose elements are derived from an existing data source.

Filtering with an if clause

Adding an if clause to the end of a comprehension filters the source items, keeping only those for which the condition is true. The if clause is evaluated for every item, and items that fail the condition are skipped entirely. They do not contribute to the result list and the expression is never evaluated for them.

pythonpython
evens = [x for x in range(20) if x % 2 == 0]

This comprehension keeps only the even numbers from the range. The condition x % 2 == 0 acts as a gate: numbers that pass enter the result, numbers that fail are discarded. You can chain multiple if clauses, which is equivalent to combining the conditions with an and operator. Every if clause must be satisfied for an item to be included.

An if clause filters items out. It does not provide an alternative value for items that fail. If you need to produce one value when a condition is true and a different value when it is false, place the conditional expression in the expression position, before the for clause. In that position, an if/else ternary expression is required because every source item must produce exactly one value in the output list.

Multiple for clauses for nested iteration

A comprehension can include more than one for clause to iterate over nested structures. The for clauses are written left to right, and the leftmost clause is the outermost loop, exactly as you would write them in nested for statements. This ordering is one of the most intuitively designed parts of Python's syntax: the comprehension reads in the same order as the equivalent loop.

pythonpython
pairs = [(x, y) for x in [1, 2] for y in [10, 20]]

This produces [(1, 10), (1, 20), (2, 10), (2, 20)]. The outer loop iterates over x values 1 and 2, and for each x the inner loop iterates over y values 10 and 20. The result contains every combination of x and y, and the order preserves the loop nesting: all pairs with x equal to 1 come before any pair with x equal to 2.

Multiple for clauses are particularly useful for flattening nested lists. Placing the inner list iteration in the rightmost for clause pulls every element up to a single flat list. This is the comprehension equivalent of the nested loop pattern covered in the article on nested lists in Python, and it is often the cleanest way to transform a grid of values into a single linear sequence.

When to use a regular loop instead

List comprehensions are powerful but they are not always the right choice. When the logic for producing each element is complex, when you need to handle exceptions inside the loop, or when the comprehension grows to include multiple for clauses and deeply nested if conditions, readability suffers. A comprehension that spans more than two lines or requires the reader to pause and mentally trace the loop order is a sign that a regular for loop would communicate the intent more clearly.

Comprehensions also build an entire new list in memory. If you are processing a very large data source and only need to iterate over the results once, a generator expression, which uses parentheses instead of square brackets, produces items one at a time without storing them all. The article on improving Python collection performance covers generator expressions and other memory-efficient patterns.

For the vast majority of beginner and intermediate use cases, list comprehensions are the right default. They are faster than equivalent loops, they express the transformation intent directly, and they are an idiomatic Python pattern that experienced readers expect to see. The key is to keep them simple. One for clause, one optional if clause, and a clear expression is a comprehension that will be understood instantly by anyone reading your code.

Rune AI

Rune AI

Key Insights

  • A list comprehension has the form [expression for item in iterable if condition].
  • The expression is evaluated for every item that passes the optional if filter.
  • Multiple for clauses flatten nested structures and run leftmost-outermost like regular nested loops.
  • An if/else in the expression position must provide a value for every item; an if at the end only filters.
  • Prefer a regular for loop when the comprehension exceeds two for clauses or becomes hard to read.
RunePowered by Rune AI

Frequently Asked Questions

What is a list comprehension in Python?

A list comprehension is a concise syntax for creating a new list by evaluating an expression for each item in an existing iterable, optionally filtering items with an if clause. It replaces a multi-line for loop that creates an empty list and appends to it with a single readable line inside square brackets.

Can I use an if and an else in a list comprehension?

Yes, but the placement depends on what you are doing. An if clause by itself at the end filters which items are included. An if/else in the expression at the beginning decides what value to produce for each item. You cannot have an if without else in the expression position because every item must produce a value.

When should I avoid using a list comprehension?

Avoid list comprehensions when the logic is too complex for a single line, when you need to handle exceptions inside the loop, when you are modifying an existing list in place rather than building a new one, or when readability suffers because the comprehension contains deeply nested for and if clauses. A regular for loop is always acceptable when clarity matters more than brevity.

Conclusion

List comprehensions are one of Python's most loved features because they replace boilerplate loop-and-append code with a single expressive line. Learn the basic pattern, add filtering when you need it, and know when to step back to a regular loop for the sake of readability.