List, Dict, and Set Comprehensions

· 5 min read · Updated March 7, 2026 · beginner
comprehensions lists dictionaries sets syntax beginner

Comprehensions let you build collections from existing data in a single, readable line. They replace verbose for loops with expressions that are both cleaner and faster. Once you see how they work, you’ll reach for them constantly.

This tutorial covers list comprehensions first since they’re the most common, then shows how the same pattern applies to dictionaries and sets.

List Comprehensions

A list comprehension creates a new list by transforming or filtering an existing iterable. The basic syntax has three parts: the expression, the iteration, and an optional condition.

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

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

Read it left to right: “x squared, for each x in range(10).” That reading direction matches how Python evaluates the comprehension.

Filtering with Conditions

Add an if clause to include only certain items:

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

# Words with more than 4 characters
words = ["cat", "elephant", "dog", "hippopotamus"]
long_words = [w for w in words if len(w) > 4]
print(long_words)
# ['elephant', 'hippopotamus']

Transforming Data

The expression doesn’t have to be a simple calculation. You can call methods, apply functions, or build complex objects:

# Convert strings to uppercase
names = ["alice", "bob", "charlie"]
upper_names = [name.upper() for name in names]
print(upper_names)
# ['ALICE', 'BOB', 'CHARLIE']

# Parse numbers from strings
strings = ["10", "20", "abc", "30"]
numbers = [int(s) for s in strings if s.isdigit()]
print(numbers)
# [10, 20]

Nested Loops

You can nest loops inside a comprehension. The outer loop comes first:

# Flatten a matrix into a single 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]

# Generate all combinations
suits = ["hearts", "diamonds", "clubs", "spades"]
ranks = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]
cards = [f"{rank} of {suit}" for suit in suits for rank in ranks]
print(len(cards))  # 52

This flattens the nested structure by pulling from the outer loop (suits) first, then the inner loop (ranks).

Dictionary Comprehensions

Dictionary comprehensions follow the same pattern but produce key-value pairs instead of single values. The syntax requires both a key and a value:

# Create a dictionary mapping numbers to their squares
squares_dict = {x: x ** 2 for x in range(5)}
print(squares_dict)
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Filtering and Transforming

You can filter using an if clause and transform both keys and values:

# 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'}

# Filter by value
prices = {"apple": 0.50, "banana": 0.30, "cherry": 2.00, "date": 1.50}
affordable = {fruit: price for fruit, price in prices.items() if price < 1.00}
print(affordable)
# {'apple': 0.5, 'banana': 0.3}

# Transform keys and values together
words = ["cat", "dog", "elephant"]
word_lengths = {word: len(word) for word in words}
print(word_lengths)
# {'cat': 3, 'dog': 3, 'elephant': 8}

Practical Example: Counting

Dictionary comprehensions shine when you need to count or group items:

# Count character frequencies in a string
text = "hello world"
char_counts = {char: text.count(char) for char in set(text)}
print(char_counts)
# {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1}

Set Comprehensions

Set comprehensions work exactly like list comprehensions but produce sets instead. This means duplicate values are automatically removed:

# Create a set of unique word lengths
words = ["cat", "dog", "elephant", "mouse", "bear"]
lengths = {len(word) for word in words}
print(lengths)
# {3, 5, 8, 4}

Notice “cat” and “dog” both have length 3, but the set only contains one 3.

Filtering with Set Comprehensions

# Extract unique first letters
names = ["Alice", "Bob", "Anna", "Ben", "Andrew"]
first_letters = {name[0] for name in names}
print(first_letters)
# {'A', 'B'}

# Get numbers divisible by 3 from a list with duplicates
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9]
divisible_by_3 = {n for n in numbers if n % 3 == 0}
print(divisible_by_3)
# {3, 6, 9}

When to Use Comprehensions

Comprehensions work well when the logic is simple and fits on one or two lines. They fail when the logic gets complex or when you need side effects.

Use comprehensions when:

  • Transforming or filtering a collection in a straightforward way
  • You want better performance than a for loop with .append()
  • The result makes the code clearer than the equivalent loop

Use a regular for loop when:

  • The body has multiple statements
  • You need to handle exceptions during iteration
  • The logic is too complex to read as a single expression
# This is fine as a comprehension
squares = [x ** 2 for x in range(10)]

# This should be a for loop — it handles errors
results = []
for item in items:
    try:
        results.append(process(item))
    except ValueError:
        results.append(None)

Generator Expressions

Sometimes you don’t need all the values at once. A generator expression uses the same syntax as a comprehension but with parentheses instead of brackets. It produces values lazily, one at a time:

# Generator expression — computes on demand
squares_gen = (x ** 2 for x in range(10))

# List comprehension — computes everything immediately
squares_list = [x ** 2 for x in range(10)]

print(next(squares_gen))  # 0 — only this value is computed
print(list(squares_gen))  # [1, 4, 9, 16, 25, 36, 49, 64, 81]

Generator expressions save memory when working with large datasets. Use them when you only need to iterate once.

Next Steps

Now you know how to build lists, dictionaries, and sets using comprehensions. These skills apply throughout Python codebases.

Continue with the next tutorial in the series to learn about *args and **kwargs, which let you build functions that accept any number of arguments.