Python Series track

Week 02 · Intermediate Track

Week 2 — Comprehensions & Generators

Write concise, readable data transformations with list, dict, and set comprehensions. Then step into generators and yield for memory-efficient iteration.

Intermediate Track2 min readFree lesson

Level: Intermediate | Prerequisite: Week 1 (Advanced Functions)

Learning Goals

  • Write list, dictionary, and set comprehensions
  • Understand generator functions and expressions
  • Write memory-efficient code

1. List Comprehensions

[expression for variable in sequence if condition] Create a list in one line.

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

#Comprehension
squares = [x * x for x in range(10)]

Add conditions:

even_sq = [x * x for x in range(10) if x % 2 == 0]
# [0, 4, 16, 36, 64]

Nested:

pairs = [(i, j) for i in range(3) for j in range(3) if i != j]

2. Dictionary and Set Comprehensions

words = ["apple", "banana", "cherry"]

#Dictionary: {key: value for ...}
length_map = {w: len(w) for w in words}
# {'apple': 5, 'banana': 6, 'cherry': 6}

#Set: {expression for ...}
unique_lens = {len(w) for w in words}
# {5, 6}

3. Generator Functions

return instead of yield. Produce results one by one as needed, not all at once.

def fib(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

for x in fib(10):
    print(x, end=" ")    # 0 1 1 2 3 5 8 13 21 34

If you want to see them all at once as a list, use list(fib(10)).

4. Generator Expressions

Use parentheses instead of brackets → save memory.

#List comprehension (eats up all the memory)
total = sum([x * x for x in range(1_000_000)])

#Generator expression (one at a time)
total = sum(x * x for x in range(1_000_000))

5. When to use which?

Situation Tool
Small data + need index List comprehension
Large data + single pass Generator
Key-value mapping Dictionary comprehension
Remove duplicates Set comprehension

Key Examples (examples/)

File Content
01_list_comp.py List comprehension
02_dict_set_comp.py Dictionary/Set
03_generator.py Generator function
04_generator_expr.py Generator expression (compare memory)

⚠️ Common Mistakes

  1. Comprehension is too long and complicated — if readability drops, just use a for loop
  2. Iterate the generator twice — once fully iterated, it will be empty. Needs to be called again.
  3. If yield is anywhere in the function, the entire function is a generator — cannot return normal values with return

❓ FAQ

Q1. Are comprehensions always faster than for loops? A. Usually slightly faster. The biggest difference is readability and expression of intent.

Q2. Can we know the length of a generator? A. No. If you need the length, convert it to a list (memory usage).

Q3. Can there be multiple yields? A. Yes. Each time it is called, it executes up to the next yield.

📝 Exercises (exercises/)

  • exercise1.md — primes from 1 to 100 (comprehension)
  • exercise2.md — mapping word lengths
  • exercise3.md — large file line-by-line generator

Next Week

Week 3. Modules and Packages

Example files

The runnable files used in this lesson. Copy them into your own project and experiment.

examples/01_list_comp.pyPython
#Basic
squares = [x * x for x in range(10)]
print(squares)

#Condition Filter
even_sq = [x * x for x in range(10) if x % 2 == 0]
print(even_sq)

#Nested
pairs = [(i, j) for i in range(3) for j in range(3) if i != j]
print(pairs)

#String Processing
words = ["Hello", "World", "Python"]
upper = [w.upper() for w in words]
print(upper)
examples/02_dict_set_comp.pyPython
words = ["apple", "banana", "cherry"]

#Dictionary Comprehension
length_map = {w: len(w) for w in words}
print(length_map)

#Inverting Key-Value
d = {"a": 1, "b": 2, "c": 3}
inv = {v: k for k, v in d.items()}
print(inv)

#Set Comprehension
unique_lens = {len(w) for w in words}
print(unique_lens)

text = "the quick brown fox jumps over the lazy dog"
unique_words = {w for w in text.split()}
print(len(unique_words))
examples/03_generator.pyPython
def fib(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

for x in fib(10):
    print(x, end=" ")
print()

#Receive all at once as a list
print(list(fib(10)))

#Infinite generator
def naturals():
    n = 1
    while True:
        yield n
        n += 1

import itertools
first_5 = list(itertools.islice(naturals(), 5))
print(first_5)
examples/04_generator_expr.pyPython
import sys

#List comprehension — eats up all the memory
list_sq = [x * x for x in range(1_000_000)]
print(f"list memory: {sys.getsizeof(list_sq):,} bytes")

#Generator expression — one at a time
gen_sq = (x * x for x in range(1_000_000))
print(f"generator memory: {sys.getsizeof(gen_sq):,} bytes")

#The result is the same
print(sum(x * x for x in range(100)))

Assignment

Goal

Select only the prime numbers between 1 and 100 and make a list. Use comprehension.

Hint

  • Define the is_prime(n) function first
  • primes = [n for n in range(2, 101) if is_prime(n)]

Input/Output Example

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Total 25

Assignment 2. Word Length Mapping

Goal

Create a {Word: Length} dictionary from a list of words.

Requirements

  • Use dictionary comprehension
  • Duplicate words only once

Input Example

words = ["apple", "banana", "apple", "cherry", "date", "banana"]

Output Example

{'apple': 5, 'banana': 6, 'cherry': 6, 'date': 4}

Assignment 3. Large File Line Generator

Goal

Write a generator read_lines(path) that yields file contents line by line.

Requirements

  • Do not load the entire large file into memory at once
  • Exclude empty lines and spaces (skip if empty after strip)

Example of use

for line in read_lines("data.txt"):
    print(line)

Challenge

  • Also write a chunked_lines(path, n) that yields lines grouped by N
Show the reference solution

Try the assignment yourself first — comparing your attempt with a working solution is where most of the learning happens.

solution1.pyPython
def is_prime(n):
    if n < 2:
        return False
    if n == 2:
        return True
    if n % 2 == 0:
        return False
    return all(n % i for i in range(3, int(n ** 0.5) + 1, 2))

primes = [n for n in range(2, 101) if is_prime(n)]
print(primes)
print(f"Total {len(primes)} items")
solution2.pyPython
words = ["apple", "banana", "apple", "cherry", "date", "banana"]

length_map = {w: len(w) for w in set(words)}
print(length_map)

#Input order maintained version
length_map2 = {}
for w in words:
    length_map2.setdefault(w, len(w))
print(length_map2)
solution3.pyPython
def read_lines(path):
    with open(path, encoding="utf-8") as f:
        for line in f:
            line = line.strip()
            if line:
                yield line

def chunked_lines(path, n):
    chunk = []
    for line in read_lines(path):
        chunk.append(line)
        if len(chunk) >= n:
            yield chunk
            chunk = []
    if chunk:
        yield chunk

#For testing (reading own file)
import sys, pathlib
self_path = pathlib.Path(__file__)
for line in read_lines(self_path):
    print(line)
print("---")
for chunk in chunked_lines(self_path, 3):
    print("Chunk:", chunk)
    print("---")

Learn this lesson with a mentor

Work through the Python Series track on your own, or join a guided cohort at our Pitampura campus and online.

Call NowEnroll Now