🔷 Introduction

Python is famous for writing powerful logic in very few lines of code.
Two of the most important tools that make Python “Pythonic” are:

  • List Comprehensions — compact syntax for creating lists
  • Generator Expressions — memory-efficient expressions for processing data lazily

These tools are essential for writing clean, efficient, and readable code, especially when dealing with transformations, filtering, and data pipelines.

Today you will learn:

✔ The structure and syntax of list comprehensions
✔ How to add conditions inside comprehensions
✔ Nested comprehensions
✔ Difference between lists and generators
✔ How to write generator expressions
✔ When to use generators for performance

Let’s begin!

🟩 1. What Is a List Comprehension?

A list comprehension is a concise way to create a list using this pattern:

new_list = [expression for item in iterable]

Example: Square numbers from 1 to 5

squares = [x * x for x in range(1, 6)]
print(squares)   # [1, 4, 9, 16, 25]

This replaces a longer loop:

squares = []
for x in range(1, 6):
    squares.append(x * x)

🟩 2. Comprehensions With Conditions

You can filter items by adding an if condition:

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

Example: Get names longer than 4 letters

names = ["Ali", "Mouad", "Sara", "Yassine"]
long_names = [n for n in names if len(n) > 4]
print(long_names)

🟩 3. Nested List Comprehensions

Useful for flattening structures or creating grids.

Example: Flatten a 2D list

matrix = [[1,2,3],[4,5,6],[7,8,9]]
flat = [num for row in matrix for num in row]
print(flat)  # [1,2,3,4,5,6,7,8,9]

Equivalent to nested loops:

flat = []
for row in matrix:
    for num in row:
        flat.append(num)

🟩 4. Dictionary & Set Comprehensions

Yes — comprehensions also work with dicts and sets.

Dictionary comprehension:

squares = {x: x*x for x in range(5)}
print(squares)

Set comprehension:

unique_squares = {x*x for x in range(-3, 4)}
print(unique_squares)

🟩 5. Generator Expressions

A generator expression looks like a list comprehension but uses parentheses instead of brackets:

gen = (x * x for x in range(1, 6))

What’s the difference?

  • List comprehension: builds the whole list in memory
  • Generator expression: produces values one at a time, only when needed (lazy evaluation)

Example:

gen = (x * x for x in range(1, 6))

for value in gen:
    print(value)

Generator expressions are excellent for large datasets, streams, and files.

🟩 6. When Should You Use Generators?

Use a generator when:

  • You are processing very large data (millions of records)
  • You don’t need to store everything in memory
  • You want to improve performance

Examples:

✔ Reading a huge file line by line
✔ Streaming data from an API
✔ Processing logs

🟧 7. Exercise Block (Solutions Hidden)

Exercise 1 — Create a list of cubes using a comprehension

Create a list of the cubes of numbers from 1 to 10.

Exercise 2 — Filter names that start with the letter “A”

Given:

names = ["Ali", "Sara", "Amine", "Yassine", "Amina"]

Create a list containing only names that start with "A".

Exercise 3 — Flatten the following nested list

nested = [[1, 2], [3, 4], [5, 6]]

Output should be: [1, 2, 3, 4, 5, 6].

Exercise 4 — Create a generator that yields even numbers from 0 to 20

Exercise 5 — Build a dictionary using a comprehension

Create:

{1:1, 2:4, 3:9, 4:16}

🟦 Conclusion

List comprehensions and generator expressions are two of the most powerful tools in Python. They help you:

  • write cleaner code
  • process data efficiently
  • reduce errors
  • improve performance

Mastering these techniques is essential for writing professional, Pythonic code.