DocsHub
Data Structures

Comprehensions

Learn how to write clean, concise list, dictionary, and set comprehensions in Python.

Comprehensions

A comprehension is a short, clean way to create a list, dictionary, or set from an existing sequence — all in one line. Instead of writing a loop that builds up a collection step by step, you express it in a single readable line.

Before comprehensions, you would write this:

numbers = [1, 2, 3, 4, 5]
squares = []

for number in numbers:
    squares.append(number ** 2)

print(squares)   # [1, 4, 9, 16, 25]

With a list comprehension:

numbers = [1, 2, 3, 4, 5]
squares = [number ** 2 for number in numbers]

print(squares)   # [1, 4, 9, 16, 25]

Same result. One line. Much cleaner.


List comprehensions

The structure is:

[expression for item in iterable]
  • expression — what you want to do with each item
  • item — the variable name for each item
  • iterable — the sequence you are looping over
# double every number
numbers = [1, 2, 3, 4, 5]
doubled = [n * 2 for n in numbers]
print(doubled)   # [2, 4, 6, 8, 10]

# convert to uppercase
names = ["ali", "sara", "omar"]
upper_names = [name.upper() for name in names]
print(upper_names)   # ['ALI', 'SARA', 'OMAR']

# get the length of each word
words = ["Python", "is", "amazing"]
lengths = [len(word) for word in words]
print(lengths)   # [6, 2, 7]

Adding a condition — filtering

You can add an if at the end to only include items that pass a test:

[expression for item in iterable if condition]
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# only even numbers
evens = [n for n in numbers if n % 2 == 0]
print(evens)   # [2, 4, 6, 8, 10]

# only numbers greater than 5
big = [n for n in numbers if n > 5]
print(big)   # [6, 7, 8, 9, 10]

A real example — filter out empty strings from a list:

data = ["Ali", "", "Sara", "  ", "Omar", ""]

clean = [name.strip() for name in data if name.strip()]
print(clean)   # ['Ali', 'Sara', 'Omar']

.strip() removes whitespace, and if name.strip() filters out anything that becomes empty after stripping.


if/else inside a comprehension

You can also transform items differently based on a condition. The if/else goes in the expression part — before the for:

[value_if_true if condition else value_if_false for item in iterable]
numbers = [1, 2, 3, 4, 5, 6]

labels = ["even" if n % 2 == 0 else "odd" for n in numbers]
print(labels)   # ['odd', 'even', 'odd', 'even', 'odd', 'even']

Another example — pass or fail:

scores = [88, 45, 72, 38, 91, 55]

results = ["pass" if score >= 50 else "fail" for score in scores]
print(results)   # ['pass', 'fail', 'pass', 'fail', 'pass', 'pass']

Notice the two different positions of if:

  • After the for → filters items in or out: [x for x in items if condition]
  • Before the for → transforms items: [a if condition else b for x in items]

They do different things. Both can be used together too.


Dictionary comprehensions

Same idea — but builds a dictionary instead of a list. Use {} and provide a key-value pair:

{key: value for item in iterable}
# square each number and store as key: value
numbers = [1, 2, 3, 4, 5]
squares = {n: n ** 2 for n in numbers}
print(squares)   # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

Build a dictionary from two lists:

names = ["Ali", "Sara", "Omar"]
scores = [88, 95, 72]

gradebook = {name: score for name, score in zip(names, scores)}
print(gradebook)   # {'Ali': 88, 'Sara': 95, 'Omar': 72}

With a condition — only include students who passed:

gradebook = {name: score for name, score in zip(names, scores) if score >= 75}
print(gradebook)   # {'Ali': 88, 'Sara': 95}

Flip keys and values:

original = {"name": "Ali", "age": 22, "city": "Lahore"}

flipped = {value: key for key, value in original.items()}
print(flipped)   # {'Ali': 'name', 22: 'age', 'Lahore': 'city'}

Set comprehensions

Same as list comprehensions — but uses {} and produces a set with no duplicates:

{expression for item in iterable}
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]

unique_squares = {n ** 2 for n in numbers}
print(unique_squares)   # {1, 4, 9, 16}

Get unique first letters from a list of names:

names = ["Ali", "Sara", "Ahmed", "Sana", "Omar"]

first_letters = {name[0] for name in names}
print(first_letters)   # {'A', 'S', 'O'}

Nested comprehensions

You can nest a comprehension inside another. This is useful for flattening nested lists or building matrices.

Flatten a nested list:

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

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

Read it left to right — for each row in matrix, for each item in that row, include item.

Build a multiplication table as a nested list:

table = [[row * col for col in range(1, 6)] for row in range(1, 6)]

for row in table:
    print(row)

Output:

[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]

Do not over-nest. One level of nesting in a comprehension is fine. Two levels gets hard to read fast. If it takes more than a few seconds to understand, rewrite it as a normal loop — readability always wins.


Comprehension vs loop — when to use which

SituationUse
Simple transformation of a sequenceComprehension
Filtering items from a sequenceComprehension
Building a dict or set from a sequenceComprehension
Complex logic with multiple stepsLoop
Side effects like printing or file writingLoop
More than two conditions or levels of nestingLoop

A good rule — if the comprehension fits comfortably on one line and reads naturally, use it. If you are squinting to understand it, use a loop.


A real example

Process a list of raw order data — clean the names, calculate totals with tax, and only keep completed orders:

orders = [
    {"customer": "  ali  ", "amount": 100, "status": "completed"},
    {"customer": "sara",    "amount": 250, "status": "pending"},
    {"customer": " omar ",  "amount": 75,  "status": "completed"},
    {"customer": "fatima",  "amount": 180, "status": "cancelled"},
    {"customer": "zainab",  "amount": 320, "status": "completed"},
]

TAX_RATE = 0.15

completed = [
    {
        "customer": order["customer"].strip().title(),
        "total": round(order["amount"] * (1 + TAX_RATE), 2)
    }
    for order in orders
    if order["status"] == "completed"
]

for order in completed:
    print(f"{order['customer']}: ${order['total']}")

Output:

Ali: $115.0
Omar: $86.25
Zainab: $368.0

Summary

TypeSyntaxReturns
List comprehension[expr for x in iter]List
List with filter[expr for x in iter if cond]Filtered list
List with transform[a if cond else b for x in iter]Transformed list
Dict comprehension{k: v for x in iter}Dictionary
Set comprehension{expr for x in iter}Set
Nested[x for row in matrix for x in row]Flat list

On this page