List Comprehensions
Introduction to Comprehensions
List comprehensions are a concise, Pythonic way to create lists. They combine a for loop and an optional condition into a single readable expression. The syntax is [expression for item in iterable]. This pattern is fundamental to writing clean, efficient Python code.
Python# Basic syntax: [expression for item in iterable] # Create a list of numbers numbers = [x for x in range(5)] print(numbers) # [0, 1, 2, 3, 4] # Transform each item doubled = [x * 2 for x in range(5)] print(doubled) # [0, 2, 4, 6, 8]
From Loop to Comprehension
Any simple loop that builds a list can be rewritten as a list comprehension—a single line of Pythonic code. The comprehension reads almost like English: 'give me n squared for each n in range(5)'.
Python# Traditional loop approach squares = [] for n in range(5): squares.append(n * n) print(squares) # [0, 1, 4, 9, 16] # Equivalent comprehension (one line!) squares2 = [n * n for n in range(5)] print(squares2) # [0, 1, 4, 9, 16] # More examples names = ['alice', 'bob', 'charlie'] upper = [name.upper() for name in names] print(upper) # ['ALICE', 'BOB', 'CHARLIE']
Filtering with if
Add an if clause at the end to filter items. Only elements where the condition is True are included in the result. The syntax is [expression for item in iterable if condition].
Python# Filter even numbers evens = [n for n in range(10) if n % 2 == 0] print(evens) # [0, 2, 4, 6, 8] # Filter and transform even_squares = [n*n for n in range(10) if n % 2 == 0] print(even_squares) # [0, 4, 16, 36, 64] # Filter strings by length words = ['hi', 'hello', 'hey', 'howdy', 'yo'] long_words = [w for w in words if len(w) > 2] print(long_words) # ['hello', 'hey', 'howdy']
Conditional Expressions (if-else)
Use a conditional expression BEFORE the 'for' to transform values differently based on a condition. Syntax: [value_if_true if condition else value_if_false for item in iterable]. This is different from filtering—every item produces output.
Python# Replace negatives with 0 nums = [5, -3, 2, -1, 4] positive = [n if n > 0 else 0 for n in nums] print(positive) # [5, 0, 2, 0, 4] # Label as even/odd labels = ['even' if n % 2 == 0 else 'odd' for n in range(5)] print(labels) # ['even', 'odd', 'even', 'odd', 'even'] # Categorize grades scores = [85, 60, 92, 45, 78] grades = ['pass' if s >= 60 else 'fail' for s in scores] print(grades) # ['pass', 'pass', 'pass', 'fail', 'pass']
Multiple Conditions
Chain multiple conditions using 'and' / 'or' in your filter. You can also use multiple if clauses (they act as 'and'). This lets you build complex filters concisely.
Python# Multiple conditions with 'and' nums = range(20) result = [n for n in nums if n % 2 == 0 and n % 3 == 0] print(result) # [0, 6, 12, 18] - divisible by both 2 AND 3 # Multiple if clauses (same as 'and') result2 = [n for n in nums if n % 2 == 0 if n % 3 == 0] print(result2) # [0, 6, 12, 18] # Using 'or' result3 = [n for n in range(10) if n < 3 or n > 7] print(result3) # [0, 1, 2, 8, 9] # Complex condition words = ['apple', 'Banana', 'cherry', 'Date'] filtered = [w for w in words if w[0].islower() and len(w) > 4] print(filtered) # ['apple', 'cherry']
Nested Loops in Comprehensions
Add multiple 'for' clauses to iterate over nested structures. The loops are evaluated left to right (outer to inner). This is powerful for combining or flattening data.
Python# Cartesian product colors = ['red', 'blue'] sizes = ['S', 'M', 'L'] combos = [(c, s) for c in colors for s in sizes] print(combos) # [('red','S'), ('red','M'), ('red','L'), # ('blue','S'), ('blue','M'), ('blue','L')] # Multiplication table table = [i * j for i in range(1, 4) for j in range(1, 4)] print(table) # [1, 2, 3, 2, 4, 6, 3, 6, 9] # With condition pairs = [(x, y) for x in range(3) for y in range(3) if x != y] print(pairs) # [(0,1), (0,2), (1,0), (1,2), (2,0), (2,1)]
Flattening Nested Lists
Nested comprehensions can flatten 2D lists into 1D. Read it as: 'for each row, for each item in row, give me item'. This is a common pattern for processing matrix-like data.
Python# 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] # With transformation doubled = [num * 2 for row in matrix for num in row] print(doubled) # [2, 4, 6, 8, 10, 12, 14, 16, 18] # With filter evens = [num for row in matrix for num in row if num % 2 == 0] print(evens) # [2, 4, 6, 8] # Flatten strings words = ['hello', 'world'] chars = [c for word in words for c in word] print(chars) # ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
Creating Nested Lists
Use a comprehension inside another comprehension to create 2D structures. The inner comprehension is the expression. This is how you build matrices or grids programmatically.
Python# Create a 3x3 matrix of zeros zeros = [[0 for _ in range(3)] for _ in range(3)] print(zeros) # [[0, 0, 0], [0, 0, 0], [0, 0, 0]] # Create identity matrix identity = [[1 if i == j else 0 for j in range(3)] for i in range(3)] print(identity) # [[1, 0, 0], [0, 1, 0], [0, 0, 1]] # Multiplication table as 2D table = [[i * j for j in range(1, 5)] for i in range(1, 5)] for row in table: print(row) # [1, 2, 3, 4] # [2, 4, 6, 8] # [3, 6, 9, 12] # [4, 8, 12, 16]
Dictionary Comprehensions
Use curly braces {} with key:value syntax to create dictionaries. The pattern is {key_expr: value_expr for item in iterable}. This is incredibly useful for transforming and inverting mappings.
Python# Basic dict comprehension squares = {n: n*n for n in range(5)} print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} # From two lists names = ['alice', 'bob', 'carol'] ages = [25, 30, 35] people = {name: age for name, age in zip(names, ages)} print(people) # {'alice': 25, 'bob': 30, 'carol': 35} # Invert a dictionary original = {'a': 1, 'b': 2, 'c': 3} inverted = {v: k for k, v in original.items()} print(inverted) # {1: 'a', 2: 'b', 3: 'c'} # With filter scores = {'alice': 85, 'bob': 62, 'carol': 91} passed = {k: v for k, v in scores.items() if v >= 70} print(passed) # {'alice': 85, 'carol': 91}
Set Comprehensions
Use curly braces {} without colons to create sets. Sets automatically remove duplicates. The pattern is {expression for item in iterable}. Great for extracting unique values.
Python# Basic set comprehension squares = {n*n for n in range(-3, 4)} print(squares) # {0, 1, 4, 9} - no duplicates! # Unique first letters names = ['alice', 'bob', 'anna', 'carol', 'charlie'] first_letters = {name[0] for name in names} print(first_letters) # {'a', 'b', 'c'} # Unique word lengths sentence = 'the quick brown fox jumps' lengths = {len(word) for word in sentence.split()} print(lengths) # {3, 4, 5} # With condition even_squares = {n*n for n in range(10) if n % 2 == 0} print(even_squares) # {0, 4, 16, 36, 64}
Generator Expressions
Use parentheses () instead of brackets to create a generator. Generators compute values lazily (on demand) and are memory-efficient for large datasets. They can only be iterated once.
Python# Generator expression (uses parentheses) gen = (n*n for n in range(5)) print(gen) # <generator object ...> # Consume with list() or iteration print(list(gen)) # [0, 1, 4, 9, 16] # Memory efficient for large data sum_million = sum(n for n in range(1_000_000)) print(sum_million) # 499999500000 # Common pattern: pass directly to functions nums = [1, 2, 3, 4, 5] total = sum(n*n for n in nums) # No extra list created! print(total) # 55 # Find first match (stops early) first_big = next(n for n in range(100) if n > 50) print(first_big) # 51
String Operations with Comprehensions
Comprehensions work beautifully with strings since strings are iterable. Transform characters, filter letters, or build new strings with join(). Essential for text processing.
Python# Extract digits from string text = 'abc123def456' digits = [c for c in text if c.isdigit()] print(digits) # ['1', '2', '3', '4', '5', '6'] print(''.join(digits)) # '123456' # Remove vowels word = 'comprehension' no_vowels = ''.join(c for c in word if c not in 'aeiou') print(no_vowels) # 'cmprhnsn' # Convert to ASCII codes ascii_codes = [ord(c) for c in 'ABC'] print(ascii_codes) # [65, 66, 67] # Capitalize words sentence = 'hello world python' titled = ' '.join(word.capitalize() for word in sentence.split()) print(titled) # 'Hello World Python'
Real-World: Data Cleaning
Comprehensions excel at data preprocessing tasks: extracting fields, normalizing text, removing invalid entries, and transforming formats. They make data pipelines readable.
Python# Clean user input raw_emails = [' Alice@MAIL.com ', 'BOB@mail.COM', ' carol@mail.com'] clean = [e.strip().lower() for e in raw_emails] print(clean) # ['alice@mail.com', 'bob@mail.com', 'carol@mail.com'] # Extract valid numbers data = ['42', 'hello', '3.14', '', '99', 'NaN'] numbers = [float(x) for x in data if x.replace('.','').isdigit()] print(numbers) # [42.0, 3.14, 99.0] # Parse CSV-like data lines = ['alice,25,engineer', 'bob,30,designer'] records = [line.split(',') for line in lines] print(records) # [['alice', '25', 'engineer'], ['bob', '30', 'designer']] # Convert to dict people = [{'name': r[0], 'age': int(r[1])} for r in records] print(people)
Real-World: Mathematical Operations
Comprehensions are perfect for vector operations, matrix manipulations, and mathematical transformations. They replace verbose loops with expressive one-liners.
Python# Vector operations vec_a = [1, 2, 3, 4] vec_b = [5, 6, 7, 8] # Element-wise addition sum_vec = [a + b for a, b in zip(vec_a, vec_b)] print(sum_vec) # [6, 8, 10, 12] # Dot product dot = sum(a * b for a, b in zip(vec_a, vec_b)) print(dot) # 70 # Transpose a matrix matrix = [[1, 2, 3], [4, 5, 6]] transpose = [[row[i] for row in matrix] for i in range(3)] print(transpose) # [[1, 4], [2, 5], [3, 6]] # Normalize values (0-1 range) data = [10, 20, 30, 40, 50] min_v, max_v = min(data), max(data) norm = [(x - min_v) / (max_v - min_v) for x in data] print(norm) # [0.0, 0.25, 0.5, 0.75, 1.0]
Performance: Comprehensions vs Loops
List comprehensions are generally 10-30% faster than equivalent for loops because they're optimized at the bytecode level. However, the real benefit is readability—use them when they make code clearer.
Pythonimport timeit # Loop version def with_loop(): result = [] for i in range(1000): result.append(i * 2) return result # Comprehension version def with_comp(): return [i * 2 for i in range(1000)] # Comprehensions are typically faster: # with_loop: ~50 microseconds # with_comp: ~35 microseconds # Generator even more memory efficient def process_large(): # Uses almost no memory for 10M items return sum(x*x for x in range(10_000_000))
When NOT to Use Comprehensions
Avoid comprehensions when: (1) Logic is complex and needs multiple statements, (2) You need side effects like printing, (3) The line becomes too long to read, (4) You need to break/continue. Keep comprehensions simple and readable.
Python# BAD: Too complex - use a loop instead # result = [x.strip().lower().replace(' ', '_') # for x in data if x and len(x) > 2 # and not x.startswith('#')] # GOOD: Break into clear steps def clean_item(x): return x.strip().lower().replace(' ', '_') def is_valid(x): return x and len(x) > 2 and not x.startswith('#') result = [clean_item(x) for x in data if is_valid(x)] # BAD: Side effects in comprehension # [print(x) for x in items] # Don't do this! # GOOD: Use a regular loop for side effects for x in items: print(x)
Best Practices Summary
1) Keep it simple—if it doesn't fit on one line comfortably, use a loop. 2) Use generator expressions for large data. 3) Name comprehensions clearly. 4) Prefer comprehensions over map/filter for readability. 5) Break complex logic into helper functions.
Python# BEST PRACTICES CHECKLIST # # ✓ Simple transformations squares = [x*x for x in nums] # ✓ Basic filtering positive = [x for x in nums if x > 0] # ✓ Use generators for large data sum(x*x for x in range(1000000)) # ✓ Readable dict comprehensions word_len = {w: len(w) for w in words} # ✓ Helper functions for complex logic clean = [normalize(x) for x in data if is_valid(x)] # ✗ Avoid: nested comprehensions > 2 levels # ✗ Avoid: side effects (print, append to external) # ✗ Avoid: lines longer than ~80 characters
Master this concept
Hands-on practice is the fastest way to learn. Head over to our interactive workspace to solve this topic's challenge.