Python - List Comprehension with Examples

List comprehension follows the pattern `[expression for item in iterable]`. This syntax replaces the traditional loop-append pattern with a single line.

Key Insights

  • List comprehensions provide a concise syntax for creating lists, reducing typical for-loops from 3-4 lines to a single expression while maintaining readability
  • Conditional logic in comprehensions enables filtering and transformation in one operation, with if-else supporting both filter and map patterns
  • Nested comprehensions handle multi-dimensional data structures efficiently but should be limited to 2-3 levels to preserve code clarity

Basic List Comprehension Syntax

List comprehension follows the pattern [expression for item in iterable]. This syntax replaces the traditional loop-append pattern with a single line.

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

# List comprehension
squares = [x ** 2 for x in range(10)]
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

The comprehension executes faster because Python optimizes it at the bytecode level. The expression x ** 2 evaluates for each element, and the results populate the list directly without explicit append calls.

# String manipulation
words = ['hello', 'world', 'python']
uppercase = [word.upper() for word in words]
# ['HELLO', 'WORLD', 'PYTHON']

# Method chaining
names = ['  alice  ', '  bob  ', '  charlie  ']
cleaned = [name.strip().title() for name in names]
# ['Alice', 'Bob', 'Charlie']

Filtering with Conditional Logic

Adding an if clause filters elements before applying the expression. The syntax becomes [expression for item in iterable if condition].

# Filter even numbers
numbers = range(20)
evens = [n for n in numbers if n % 2 == 0]
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# Filter and transform
prices = [10.50, 25.00, 5.75, 100.00, 15.25]
expensive = [p * 1.1 for p in prices if p > 20]
# [27.5, 110.0]

Multiple conditions combine using and or or operators:

# Multiple filter conditions
data = range(1, 51)
result = [x for x in data if x % 3 == 0 and x % 5 == 0]
# [15, 30, 45]

# Complex filtering
users = [
    {'name': 'Alice', 'age': 25, 'active': True},
    {'name': 'Bob', 'age': 17, 'active': True},
    {'name': 'Charlie', 'age': 30, 'active': False},
    {'name': 'David', 'age': 22, 'active': True}
]

active_adults = [u['name'] for u in users if u['age'] >= 18 and u['active']]
# ['Alice', 'David']

If-Else Expressions in Comprehensions

When you need conditional transformation rather than filtering, place the if-else before the for clause: [true_expr if condition else false_expr for item in iterable].

# Categorize numbers
numbers = [-5, 3, -2, 8, -1, 0, 4]
signs = ['positive' if n > 0 else 'negative' if n < 0 else 'zero' for n in numbers]
# ['negative', 'positive', 'negative', 'positive', 'negative', 'zero', 'positive']

# Apply different transformations
values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
transformed = [x ** 2 if x % 2 == 0 else x ** 3 for x in values]
# [1, 4, 27, 16, 125, 36, 343, 64, 729, 100]

Combining both patterns—transformation with if-else and filtering with trailing if:

# Transform evens, filter out odds
numbers = range(1, 11)
result = [x * 2 if x % 2 == 0 else x for x in numbers if x > 3]
# [5, 8, 7, 16, 9, 20]

Nested List Comprehensions

Nested comprehensions process multi-dimensional structures. The outer loop executes first, followed by inner loops.

# Flatten a 2D matrix
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Create a multiplication table
table = [[i * j for j in range(1, 6)] for i in range(1, 6)]
# [[1, 2, 3, 4, 5],
#  [2, 4, 6, 8, 10],
#  [3, 6, 9, 12, 15],
#  [4, 8, 12, 16, 20],
#  [5, 10, 15, 20, 25]]

Nested comprehensions with filtering:

# Extract specific elements from matrix
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
evens_above_five = [num for row in matrix for num in row if num > 5 and num % 2 == 0]
# [6, 8, 10, 12]

# Cartesian product with condition
colors = ['red', 'blue', 'green']
sizes = ['S', 'M', 'L']
combinations = [(c, s) for c in colors for s in sizes if not (c == 'red' and s == 'L')]
# [('red', 'S'), ('red', 'M'), ('blue', 'S'), ('blue', 'M'), ('blue', 'L'), 
#  ('green', 'S'), ('green', 'M'), ('green', 'L')]

Working with Dictionaries and Sets

List comprehensions extend to dictionary and set comprehensions with minimal syntax changes.

# Dictionary comprehension
words = ['apple', 'banana', 'cherry']
word_lengths = {word: len(word) for word in words}
# {'apple': 5, 'banana': 6, 'cherry': 6}

# Invert dictionary
original = {'a': 1, 'b': 2, 'c': 3}
inverted = {v: k for k, v in original.items()}
# {1: 'a', 2: 'b', 3: 'c'}

# Set comprehension (automatic deduplication)
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique_squares = {x ** 2 for x in numbers}
# {1, 4, 9, 16}

Practical dictionary filtering and transformation:

# Filter and transform dictionary
products = {
    'laptop': 1200,
    'mouse': 25,
    'keyboard': 80,
    'monitor': 300,
    'cable': 10
}

expensive = {k: v * 0.9 for k, v in products.items() if v > 50}
# {'laptop': 1080.0, 'keyboard': 72.0, 'monitor': 270.0}

Performance Considerations

List comprehensions generally outperform equivalent for-loops due to optimization at the interpreter level.

import timeit

# Performance comparison
def traditional_loop():
    result = []
    for i in range(1000):
        result.append(i ** 2)
    return result

def comprehension():
    return [i ** 2 for i in range(1000)]

# timeit shows comprehension is typically 15-20% faster

However, generator expressions offer better memory efficiency for large datasets:

# List comprehension - creates entire list in memory
squares_list = [x ** 2 for x in range(1000000)]  # ~8MB memory

# Generator expression - lazy evaluation
squares_gen = (x ** 2 for x in range(1000000))   # minimal memory

# Use generator when you only need to iterate once
total = sum(x ** 2 for x in range(1000000))

Real-World Applications

Processing API responses:

# Extract specific fields from API data
api_response = [
    {'id': 1, 'name': 'Item A', 'price': 10.50, 'stock': 100},
    {'id': 2, 'name': 'Item B', 'price': 25.00, 'stock': 0},
    {'id': 3, 'name': 'Item C', 'price': 15.75, 'stock': 50}
]

available_items = [
    {'name': item['name'], 'price': item['price']} 
    for item in api_response 
    if item['stock'] > 0
]
# [{'name': 'Item A', 'price': 10.5}, {'name': 'Item C', 'price': 15.75}]

File processing:

# Parse CSV-like data
lines = ['name,age,city', 'Alice,25,NYC', 'Bob,30,LA', 'Charlie,35,Chicago']
data = [dict(zip(lines[0].split(','), line.split(','))) for line in lines[1:]]
# [{'name': 'Alice', 'age': '25', 'city': 'NYC'}, ...]

Data validation and cleaning:

# Clean and validate email list
emails = ['user@example.com', 'invalid-email', 'admin@test.com', '', 'test@domain']
valid_emails = [
    email.lower().strip() 
    for email in emails 
    if email and '@' in email and '.' in email.split('@')[1]
]
# ['user@example.com', 'admin@test.com']

List comprehensions balance conciseness with readability. Use them for straightforward transformations and filtering. When logic becomes complex or nesting exceeds two levels, traditional loops with explicit logic provide better maintainability.

Liked this? There's more.

Every week: one practical technique, explained simply, with code you can use immediately.