← all snippets
Lesson

Comprehensions & Generators

Python's most-loved one-liners. Learn to turn loops into clear, fast expressions — and when a lazy generator saves your memory.

1. The loop → comprehension move

Any loop that builds a list by appending can usually become a comprehension. It reads as “this expression, for each item”.

# the long way
squares = []
for n in range(6):
    squares.append(n * n)

# the comprehension
squares = [n * n for n in range(6)]
# [0, 1, 4, 9, 16, 25]

2. Add a filter

A trailing if keeps only the items you want.

evens = [n for n in range(10) if n % 2 == 0]
# [0, 2, 4, 6, 8]

names = ["  Asha ", "ravi", ""]
clean = [s.strip().title() for s in names if s.strip()]
# ['Asha', 'Ravi']

3. Dict and set comprehensions

Same idea, different brackets. Use {k: v ...} for dicts, {x ...} for sets (which drop duplicates).

prices = {"pen": 10, "book": 250, "bag": 900}
# discount everything 10%
sale = {name: round(p * 0.9) for name, p in prices.items()}
# {'pen': 9, 'book': 225, 'bag': 810}

first_letters = {w[0] for w in ["apple", "avocado", "banana"]}
# {'a', 'b'}

4. Generators — lazy and light

Swap the [ ] for ( ) and you get a generator: it produces values one at a time instead of building the whole list in memory. Perfect for big or infinite streams.

# a list of a billion squares would eat your RAM.
# a generator computes each square only when asked:
squares = (n * n for n in range(1_000_000_000))
print(next(squares))   # 0
print(next(squares))   # 1

# summing a huge range without ever storing it:
total = sum(n * n for n in range(1_000_000))
# 333332833333500000
Rule of thumb: if you only need to iterate once (sum, max, any, a for-loop), reach for a generator. If you need to keep or index the result, build a list.

5. Your own generator with yield

For logic too complex for one line, write a function that yields. Each yield pauses the function and hands back a value.

def fibonacci(limit):
    a, b = 0, 1
    while a < limit:
        yield a
        a, b = b, a + b

print(list(fibonacci(50)))
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

6. When NOT to use them

Comprehensions are for building a collection. If you're only causing side effects (printing, saving), a plain loop is clearer — don't write a comprehension just to be clever.

# hard to read — avoid
[print(x) for x in items]

# clear — prefer
for x in items:
    print(x)

That's the whole toolkit. Practice on the daily snippets — you'll spot loops begging to become comprehensions.