Goal

You’ll be able to write list comprehensions confidently, and understand when a generator is genuinely the better choice over a list, based on real memory usage, not just syntax preference.

Learn

A list comprehension is a compact way to build a list from an existing iterable, often replacing a longer for-loop pattern:

# Traditional loop
squares = []
for x in range(10):
    squares.append(x ** 2)

# Equivalent list comprehension
squares = [x ** 2 for x in range(10)]

Comprehensions can also filter, using an optional condition:

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

A generator looks almost identical, using parentheses instead of square brackets, but works fundamentally differently:

squares_list = [x ** 2 for x in range(1000000)]   # builds the ENTIRE list in memory at once
squares_gen = (x ** 2 for x in range(1000000))    # generates values one at a time, on demand

The genuinely important difference: a list comprehension computes and stores every single value in memory immediately. A generator computes each value only when asked for it, one at a time, never holding the whole sequence in memory at once. For a million items, this is a massive practical difference — the list version uses significant memory upfront, while the generator uses almost none, since it never actually creates the full sequence at once.

The real-world guidance: use a list comprehension when you genuinely need all the values available at once (like sorting them, or accessing by index); use a generator when you’re just going to iterate through values one at a time and don’t need them all simultaneously, especially for large sequences.

Decision Task

You need to process a sequence of 10 million numbers, checking each one against a condition, but you’ll only ever look at them one at a time in a single loop, never needing random access or the full list simultaneously. Before reading on: would a list comprehension or a generator expression be the better practical choice, and why?

Show Answer

A generator expression — since you only need to process each value once, sequentially, a generator avoids ever holding all 10 million values in memory simultaneously, computing each one on demand instead. A list comprehension would build and store the entire 10-million-item list in memory upfront, using significant memory for no real benefit given how the data is actually being used here.

Common Mistake

Defaulting to list comprehensions for every situation out of habit, even when processing very large sequences where a generator would use dramatically less memory for the exact same practical result. The syntax difference (brackets vs. parentheses) is small, but the memory behavior difference can be genuinely significant for large-scale data processing.

Practice Questions

1. Write a list comprehension that creates a list of cubes (x**3) for numbers 1 through 5.

Show Answer

cubes = [x ** 3 for x in range(1, 6)]

2. Write a list comprehension that filters a list called numbers, keeping only values greater than 10.

Show Answer

[n for n in numbers if n > 10]

3. What’s the key syntactic difference between a list comprehension and a generator expression?

Show Answer

Square brackets [ ] for a list comprehension versus parentheses ( ) for a generator expression.

4. True or False: a generator expression computes and stores all its values in memory immediately, the same as a list comprehension.

Show Answer

False — a generator computes each value only when actually asked for it, never holding the full sequence in memory at once, unlike a list comprehension.

5. When would a list comprehension genuinely be the better choice over a generator, despite using more memory?

Show Answer

When you need all the values available at once — for example, to sort them, access by index, or iterate through the full collection multiple times, which a generator (being single-use, one value at a time) doesn’t support the same way.

Try It Yourself

Without looking back, write a generator expression (not a list comprehension) that would generate the squares of numbers from 1 to 1000, without actually computing them all upfront.

Show Answer

squares_gen = (x ** 2 for x in range(1, 1001)) — using parentheses instead of square brackets, meaning values are computed one at a time as they’re actually needed, not all at once upfront.

Quick Check

1. What does a list comprehension let you do concisely?

Show Answer

Build a list from an existing iterable, often replacing a longer for-loop.

2. What symbol distinguishes a generator expression from a list comprehension?

Show Answer

Parentheses ( ) instead of square brackets [ ].

3. Does a generator compute all its values immediately, or on demand?

Show Answer

On demand, one at a time, only when actually asked for.

4. Why might a generator be preferred for processing a very large sequence?

Show Answer

It avoids holding the entire sequence in memory at once, using significantly less memory than a list comprehension would for the same data.

5. Can a list comprehension include a filtering condition?

Show Answer

Yes, using an optional if clause, e.g. [x for x in range(20) if x % 2 == 0].

تحميل هذا الباب / Download this Chapterنسخة كاملة للدراسة بدون إنترنت، مع الأسئلة والإجابات والصور المتاحة.