List Comprehensions in Depth
List comprehensions are one of Python’s most elegant and expressive features.
Chapter 2: Control Structures and Functions
Sub-chapter: List Comprehensions in Depth
List comprehensions are one of Python’s most elegant and expressive features.
They provide a concise, readable, and efficient way to create, transform, and filter lists — all in a single line of code.
Instead of writing multiple lines with loops and conditional statements, list comprehensions let you express the same logic compactly, often improving both performance and clarity.
🧠 Why Use List Comprehensions?
List comprehensions are:
- ✅ Compact — replace multi-line loops with a single expression
- ⚡ Fast — execute faster than equivalent
forloops due to internal optimization - 🧱 Readable — clearly express intent (“create a new list based on this rule”)
- ♻️ Functional — align with Python’s “declarative” style for transformations
⚙️ Basic Syntax
new_list = [expression for item in iterable if condition]
| Component | Description |
|---|---|
| expression | Operation or transformation applied to each item |
| item | Variable representing each element in the iterable |
| iterable | Source sequence (list, tuple, range, string, etc.) |
| condition (optional) | Filters elements that satisfy a condition |
🧩 Example 1 — Creating a List of Squares
Traditional loop:
squares = []
for x in range(1, 11):
squares.append(x ** 2)
List comprehension:
squares = [x ** 2 for x in range(1, 11)]
Output:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
💡 The list comprehension is shorter, faster, and easier to read.
🧮 Example 2 — Filtering with a Condition
Filter even numbers from 1 to 20.
even_numbers = [x for x in range(1, 21) if x % 2 == 0]
Output:
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
Here, the if clause filters out all numbers that are not divisible by 2.
🧠 Example 3 — Transforming Strings
Convert a list of words into uppercase versions:
words = ["python", "rocks", "hard"]
uppercased = [word.upper() for word in words]
print(uppercased)
Output:
['PYTHON', 'ROCKS', 'HARD']
🧩 Example 4 — Combining Elements from Two Lists
You can nest multiple loops inside a comprehension.
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
pairs = [(num, char) for num in list1 for char in list2]
print(pairs)
Output:
[(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'), (2, 'c'), (3, 'a'), (3, 'b'), (3, 'c')]
🎯 This is equivalent to a Cartesian product — every element in list1 paired with every element in list2.
🧱 Example 5 — Nested List Comprehensions (Flattening Lists)
Suppose you have a 2D matrix (list of lists) and you want to flatten it into a single list.
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened)
Output:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Explanation:
- The first
for row in matrixiterates over each sublist. - The second
for num in rowiterates over elements in each sublist.
⚙️ Example 6 — Using Conditional Expressions Inside Comprehensions
You can add a conditional expression in the output expression, not just in the filter.
status = ["even" if x % 2 == 0 else "odd" for x in range(1, 6)]
print(status)
Output:
['odd', 'even', 'odd', 'even', 'odd']
This expression runs the inline conditional (x % 2 == 0) and assigns "even" or "odd" accordingly.
🧩 Example 7 — Working with Strings
Extract vowels from a word:
word = "recursion"
vowels = [ch for ch in word if ch in "aeiou"]
print(vowels)
Output:
['e', 'u', 'i', 'o']
🧮 Example 8 — List of Tuples (Index + Value)
You can use enumerate() to generate index-value pairs in a list comprehension.
names = ["Alice", "Bob", "Charlie"]
indexed = [(i, name) for i, name in enumerate(names, start=1)]
print(indexed)
Output:
[(1, 'Alice'), (2, 'Bob'), (3, 'Charlie')]
🧠 Example 9 — Converting Nested Data Structures
Turn a dictionary into a list of formatted strings:
scores = {"Alice": 90, "Bob": 85, "Charlie": 95}
summary = [f"{name} scored {score}" for name, score in scores.items()]
print(summary)
Output:
['Alice scored 90', 'Bob scored 85', 'Charlie scored 95']
🧩 Example 10 — Nested Conditionals and Multiple Filters
You can chain multiple if conditions inside a comprehension.
numbers = [x for x in range(1, 30) if x % 2 == 0 if x % 3 == 0]
print(numbers)
Output:
[6, 12, 18, 24]
This keeps only numbers divisible by both 2 and 3.
🧰 Advanced Concepts — Performance and Alternatives
While list comprehensions are compact, they shouldn’t replace readability.
For very large data sets or memory-intensive operations, consider:
| Alternative | Description |
|---|---|
| Generator expressions | Use parentheses () instead of brackets [] to create items lazily, saving memory. |
| map() / filter() | Functional equivalents that can be combined for clarity. |
Example:
squares = (x**2 for x in range(1, 1_000_000)) # generator, not a list
⚡ Use generator expressions when you don’t need the full list in memory at once.
🧮 Comparison: For Loops vs List Comprehensions
| Task | For Loop | List Comprehension |
|---|---|---|
| Create squares | 4 lines | 1 line |
| Filter values | Requires if + append() | Inline if |
| Readability | Verbose | Clean and declarative |
| Performance | Slightly slower | Optimized and faster |
🧠 Common Pitfalls
- ⚠️ Too much logic in one line — makes code unreadable.
- ⚠️ Nested comprehensions — can be confusing beyond two levels.
- ⚠️ Memory-heavy results — prefer generators for large data.
Example of overcomplication (avoid this):
[x*y for x in range(10) for y in range(10) if (x*y) % 2 == 0 if x != y]
✍️ Rule of thumb: if it takes more than a single screen to understand, use a
forloop.
🧾 Key Takeaways
- List comprehensions are compact, powerful, and expressive.
- Syntax:
[expression for item in iterable if condition]. - You can include multiple loops and conditions.
- Great for filtering, transforming, flattening, and generating data.
- Prefer readability over cleverness — clean code always wins.
Mastering list comprehensions not only improves your Python fluency but also teaches you to think declaratively — expressing what you want to achieve, not how to do it.