Concepts / Generator Expressions

Generator Expressions

List comprehensions are a concise syntax for creating a new list by transforming or filtering elements from an existing list.

  • Programming

From Source Items to a New List

A list comprehension is a concise way to create a new list by transforming or filtering elements from an existing list. Instead of describing the process as several separate steps, you place the transformation, the source iterable, and an optional condition into one expression.

python
Output
squares is [1, 4, 9, 16]. Each source item is transformed, and each transformed result is placed into the new list.
takes each itemis transformedadds resultnumbers[1, 2, 3, 4]numberone source itemnumber * numbertransformationsquares[1, 4, 9, 16]
How does each item move from the source iterable through the optional condition and expression to become an element in the resulting list?

Reading the Comprehension Structure

The basic list comprehension syntax is [expression for item in iterable if condition]. The condition is optional.

optional[starts the listexpressionvalue added to resultforiteratesitemcurrent source itemintakes items fromiterablesource collectionif conditionoptional filter]ends the list
Which part produces the output, which part supplies the items, and where does the optional condition fit?
PartPurposeExample
expressionDetermines the value added to the new listnumber * number
itemNames the current item from the sourcenumber
iterableProvides the source itemsnumbers
conditionOptionally decides whether an item continuesnumber % 2 == 0

The roles of the main list comprehension components.

Read the structure from left to right, but understand its operation as a process. The iterable supplies an item. If a condition is present, that item is checked. When it passes, the expression is applied and its result is added to the new list. Without a condition, every source item reaches the expression.

Filtering Before Transforming

Keep Even Numbers and Double Them

Create a new list containing twice each even number in the source list [1, 2, 3, 4, 5].

Choose the expression: The desired output is twice the item, so the expression is number * 2.

Choose the iterable: The source list is [1, 2, 3, 4, 5].

Add the condition: Only even numbers should continue, so the condition is number % 2 == 0.

Assemble the comprehension: Place the expression first, then the for item in iterable part, followed by the optional if condition.

Trace the items: The items 1, 3, and 5 fail the condition. The items 2 and 4 pass, so the expression produces 4 and 8.

[4, 8]

numbers = [1, 2, 3, 4, 5] doubled_even = [number * 2 for number in numbers if number % 2 == 0]

checkfailspassesadd valuesource itemconditionno resultnew-list itemexpression
What happens to an input item when it passes the condition, and what happens when it fails before the transformation is applied?

Nested Source Loops

Nested list comprehensions combine multiple sources. The outer loop runs first. For each item produced by that outer loop, the inner loop runs completely. This means the order of the loops matters when tracing which combinations are considered.

python
Output
coordinates is [(1, "a"), (1, "b"), (2, "a"), (2, "b")]. The inner loop completes for row 1 before the outer loop moves to row 2.

What do you think happens?

What order will the pairs appear in for [(row, column) for row in [1, 2] for column in ["a", "b"]]?

  • [(1, "a"), (1, "b"), (2, "a"), (2, "b")]
  • [(1, "a"), (2, "a"), (1, "b"), (2, "b")]
  • [(2, "b"), (2, "a"), (1, "b"), (1, "a")]
Reveal answer

Answer: [(1, "a"), (1, "b"), (2, "a"), (2, "b")]

The outer loop selects row 1 first, and the inner loop runs completely for that row. Only after columns "a" and "b" have been processed does the outer loop select row 2.

Mistakes in Structure

  • Putting the expression after the loop instead of before it

    The basic structure places the expression before for item in iterable.

    Fix: [number * 2 for number in numbers]

  • Leaving out the source iterable

    The comprehension needs an iterable after in so it knows where items come from.

    Fix: [number * 2 for number in numbers]

  • Treating the condition as the output expression

    The expression determines what is added to the new list, while an optional condition determines which items continue.

    Fix: [number for number in numbers if number % 2 == 0]

  • Applying the condition before naming the source item

    The source item and iterable belong in the for item in iterable part. The optional if condition follows that part.

    Fix: [number * 2 for number in numbers if number % 2 == 0]

When debugging, expand the comprehension into its conceptual sequence: identify the source iterable, inspect one item, evaluate the condition if present, and then evaluate the expression. This mirrors the item flow described for list comprehensions and makes misplaced components easier to spot.

Practice the Item Flow

EASY

Write a list comprehension that takes the source list [3, 6, 9, 12], keeps only items greater than 6, and transforms each retained item by adding 1.

Hints
  • The expression should add 1 to the current item.
  • The iterable is the source list.
  • Place the condition after the iterable.
python
Output
result is [10, 13]. The values 3 and 6 fail the condition. The values 9 and 12 pass, then become 10 and 13 through the expression.

Key Takeaways

  1. A list comprehension creates a new list by transforming or filtering items from an existing list.
  2. Its basic structure is [expression for item in iterable if condition], with the condition optional.
  3. The source iterable supplies items, the condition optionally filters them, and the expression produces values for the new list.
  4. When multiple sources are nested, the outer loop runs first and the inner loop completes for each outer item.
  5. To debug a comprehension, trace one source item at a time and check the placement of the expression, iterable, and condition.

Key Takeaways

  • List comprehensions provide concise syntax for creating a new list from source items.
  • The expression comes first, followed by the source loop and optional condition.
  • A condition filters items before the expression creates their result values.
  • Nested comprehensions process the outer loop first and complete the inner loop for each outer item.
  • Tracing each item through the structure is an effective way to write and debug comprehensions.