By WebNest Studio Engineering Team
Python Tutorial
Python Comprehensions and Generator Expressions
Comprehensions are a concise, expressive way to build a new list, dictionary, or set from an existing iterable, in a single readable line instead of a multi-line for loop with an accumulator variable. They are one of the most distinctively "Pythonic" features of the language.
Closely related is the generator expression, which uses similar syntax but produces values lazily, one at a time, instead of building the entire collection in memory at once — an important distinction when working with large or infinite sequences.
Why it matters
A comprehension builds a list, dictionary or set from another collection in a single readable line, and Python programmers use them everywhere in place of a loop with append. You need to read them comfortably to understand other people's code, and writing them well is one of the clearest signs of fluency in the language.
List Comprehensions
A list comprehension has the form [expression for item in iterable if condition], where the "if condition" part is optional. It produces a new list by evaluating the expression once for every item in the iterable that satisfies the condition. This replaces the common pattern of creating an empty list and calling .append() inside a for loop.
Dictionary and Set Comprehensions
The same pattern extends to dictionaries and sets using curly braces. A dictionary comprehension, {key_expr: value_expr for item in iterable}, builds a new dictionary. A set comprehension, {expression for item in iterable}, builds a new set and automatically removes duplicates, just like the set() constructor would.
Generator Expressions
A generator expression looks almost identical to a list comprehension but uses parentheses instead of square brackets: (expression for item in iterable). Rather than building the whole result in memory immediately, it returns a generator object that produces each value on demand as you iterate over it, which makes it far more memory-efficient for large datasets or when you only need to consume the values once.
Examples
List, dictionary, and set comprehensions
numbers = [1, 2, 3, 4, 5, 6]
squares = [n ** 2 for n in numbers]
print(squares)
evens_only = [n for n in numbers if n % 2 == 0]
print(evens_only)
square_map = {n: n ** 2 for n in numbers}
print(square_map)
remainders = {n % 3 for n in numbers}
print(remainders)
[1, 4, 9, 16, 25, 36]
[2, 4, 6]
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36}
{0, 1, 2}
A generator expression computes values lazily
numbers = [1, 2, 3, 4, 5]
gen = (n ** 2 for n in numbers)
print(type(gen))
print(sum(gen)) # generator is consumed here
print(sum(gen)) # already exhausted, nothing left
<class 'generator'>
55
0
Common Mistakes
- Writing an overly complex comprehension with several nested loops and conditions, which becomes harder to read than a plain for loop — comprehensions should stay simple.
- Trying to reuse a generator expression after it has already been fully consumed, forgetting that a generator can only be iterated once.
- Confusing a set comprehension {x for x in ...} with a dictionary comprehension {k: v for ...} — the presence of a colon is what makes it a dictionary.
- Using a list comprehension purely for its side effects (like calling print inside it) instead of using a plain for loop, which wastes the memory of building a throwaway list.
Exercise
Using comprehensions, print the squares of the even numbers from 1 to 10, then a dictionary mapping each word to its length, then the sum of the squares of 1 to 3 computed with a generator expression.
Expected output: [4, 16, 36, 64, 100], {'hi': 2, 'python': 6}, 14 (one per line)
# TODO: list comprehension: squares of the even numbers from 1 to 10
words = ["hi", "python"]
# TODO: dictionary comprehension: word -> length
# TODO: generator expression inside sum(): squares of 1, 2 and 3
Show hints
- The pattern is
[expression for item in iterable if condition]. - A dictionary comprehension uses braces and
key: value. A generator expression can be passed straight tosum(...).
Show solution
print([n * n for n in range(1, 11) if n % 2 == 0])
words = ["hi", "python"]
print({word: len(word) for word in words})
print(sum(n * n for n in range(1, 4)))
Quick quiz
1. What does [x * 2 for x in range(3)] produce?
- A. [2, 4, 6]
- B. [0, 1, 2]
- C. [0, 2, 4]
- D. [1, 2, 3]
Show answer
C. range(3) gives 0, 1 and 2, and each is doubled.
2. What does (x * 2 for x in range(3)) create?
- A. A tuple
- B. A list
- C. A set
- D. A generator, which produces values one at a time when asked
Show answer
D. Parentheses make a generator expression. Nothing is computed until it is iterated.
3. In a comprehension that filters, where is the if written?
- A. After the for clause
- B. Before the for
- C. Outside the brackets
- D. It cannot be filtered
Show answer
A. The filter goes at the end: [x for x in items if x > 0].
Interview questions
What is the difference between a list comprehension and a generator expression?
Show answer
A list comprehension, in square brackets, builds the whole list in memory immediately. A generator expression, in parentheses, creates an object that computes each value only when it is requested and keeps nothing afterwards. Use a generator for large or unbounded data, or when the result is consumed once, for example by sum() or any(); use a list when the values are needed more than once or need indexing.
When should a comprehension not be used?
Show answer
When it stops being easy to read: several nested loops, a complicated condition, or logic that needs more than one statement are clearer as an ordinary loop. A comprehension should also not be used only for its side effects, such as calling print for each item; that is what a for loop is for.
Key Points to Remember
- List comprehensions [expr for item in iterable if cond] build a new list concisely from an existing iterable.
- The same bracket-swap pattern produces dictionary ({k: v for ...}) and set ({expr for ...}) comprehensions.
- Generator expressions (expr for item in iterable) use parentheses and produce values lazily, saving memory.
- A generator can only be iterated through once; after it is exhausted, it yields nothing further.
Practice in the playground
Write and run your own code for this topic, or start from the exercise or an example. Runs Python in your browser. Your code for each topic is kept in this browser.
Run the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
Written by
WebNest Studio Engineering Team
Practical lessons from developers working with Java, Python, React, databases and production systems.
Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering