Python List Comprehensions

In the last lesson you learned List Slicing, which is how you grab a piece of a list. Now we go one step further. Instead of pulling parts out of a list, you often want to build a brand new list from one you already have. Maybe you have a list of prices and you want all of them with tax added. You could write a loop for that. But Python gives you a shorter, cleaner way. It is called a list comprehension.

πŸ€” Why List Comprehensions?

Say you have some numbers and you want a new list where every number is doubled. The normal way is to make an empty list, loop over the numbers, and add each doubled value one by one.

Here is that loop doing exactly that:

nums = [1, 2, 3, 4]
doubled = []
for n in nums:
doubled.append(n * 2)
print(doubled)

Output

[2, 4, 6, 8]

That works fine. But see how much typing it takes just to say β€œdouble each number”? You need three extra lines for one simple idea. A list comprehension lets you say the same thing in a single line. That is the pain it solves. Less noise, same result.

🧩 What Is a List Comprehension?

A list comprehension is a short way to build a new list from a sequence you already have. You write the rule for each item right inside the square brackets. Then Python builds the whole list comprehension for you.

Think of it like a small factory. Raw items go in on one side. Each one gets the same treatment. A finished list comes out the other side. You describe the treatment once, and the factory handles the rest.

The shape looks like this:

new_list = [expression for item in sequence]

Let me break that down in plain words:

  • expression is what you want each new item to be. This is the work, like n * 2.
  • item is the name for one thing as you go through the sequence. You pick this name.
  • sequence is the list (or range, or string) you are reading from.

Read it left to right and it almost sounds like English. β€œGive me n * 2 for each n in nums.”

πŸͺ„ The Same Job, Two Ways

Here is the doubling example again. This time the comprehension sits right next to the loop. Both produce the exact same list.

This is the loop version you already saw:

# The loop way
nums = [1, 2, 3, 4]
doubled = []
for n in nums:
doubled.append(n * 2)

And this is the comprehension version:

# The comprehension way
nums = [1, 2, 3, 4]
doubled = [n * 2 for n in nums]
print(doubled)

Output

[2, 4, 6, 8]

Look at the two side by side. The n * 2 is your expression. The for n in nums is the same loop header you already know. The comprehension just folds the empty list, the loop, and the append into one tidy line.

Tip

A good way to read any comprehension is back to front. First spot the for ... in ... part to see what you are looping over. Then look at the expression on the left to see what happens to each item.

Here is the same idea with text. Say Alex has a list of names and wants them all in uppercase for a header row.

names = ["alex", "riya", "arjun"]
shouted = [name.upper() for name in names]
print(shouted)

Output

['ALEX', 'RIYA', 'ARJUN']

The expression here is name.upper(). Same shape, different work.

πŸ” Adding a Condition

Often you do not want every item. You only want the ones that pass a test. Maybe just the positive numbers, or just the even ones. For that you add an if condition at the end of the comprehension.

The shape grows a little:

new_list = [expression for item in sequence if condition]

The if condition works like a filter. An item is only included when the condition is true. Everything else is skipped.

Say you have a mix of positive and negative numbers and you only want to keep the positive ones.

nums = [4, -2, 7, -9, 3, -1]
positives = [x for x in nums if x > 0]
print(positives)

Output

[4, 7, 3]

Notice the expression here is just x. You are not changing the numbers. You are only deciding which ones to keep. The if x > 0 does the choosing. Each negative number fails the test, so it never gets into the new list.

Now let us combine both ideas. We will change the items and filter them at the same time. Here we keep only the even numbers and square each one.

nums = [1, 2, 3, 4, 5, 6]
even_squares = [n * n for n in nums if n % 2 == 0]
print(even_squares)

Output

[4, 16, 36]

Walk through it slowly. n % 2 == 0 keeps only the even numbers, so 2, 4, and 6 get through. Then n * n squares each of those. The odd numbers were dropped before the squaring ever happened.

Note

The if here filters which items get in. There is a different kind of if (a full if-else) that changes the value, but that goes in the expression part, not at the end. We are keeping to the simple filter for now.

🧠 A Real Example

Imagine you run a small online store. You have a list of prices and you want a new list with a fifteen percent discount applied. But you only want it for items that cost more than 100. Cheaper items stay out of the sale.

Here is the whole thing in one line:

prices = [50, 120, 80, 200, 99, 150]
sale_prices = [round(p * 0.85, 2) for p in prices if p > 100]
print(sale_prices)

Output

[102.0, 170.0, 127.5]

Read it back to front. Loop over prices, keep only the ones where p > 100, then for each price that passed, compute p * 0.85 and round it to two decimals. The prices 120, 200, and 150 passed the test. The rest were under the limit, so they were left out. This builds a brand new list and never touches the original prices.

⚠️ Common Mistakes

A few things go wrong when people first use comprehensions.

  • Cramming too much logic into one line. A comprehension should stay readable. If you find yourself nesting loops and conditions until it is a wall of text, stop and use a normal loop instead. Short and clear beats short and confusing.
# ❌ Avoid: too much packed in, hard to read at a glance
result = [x * y for x in range(10) for y in range(10) if x != y if x + y > 5]
# βœ… Good: a plain loop when the logic is heavy
result = []
for x in range(10):
for y in range(10):
if x != y and x + y > 5:
result.append(x * y)
  • Forgetting that the if goes at the end (for filtering). When you are only keeping or dropping items, the condition belongs after the for part.
# ❌ Avoid: this is not how a filter is written
evens = [n if n % 2 == 0 for n in nums] # SyntaxError
# βœ… Good: filter condition goes at the end
evens = [n for n in nums if n % 2 == 0]
  • Expecting it to change the original list. A comprehension always builds a new list. The list you read from is not changed, so remember to store the result in a variable.

βœ… Best Practices

  • Reach for a comprehension when the goal is β€œbuild a new list from this one.” That is exactly what it is made for.
  • Keep it to one transformation and at most one simple filter. The moment it gets hard to read out loud, switch to a regular loop.
  • Pick a clear name for the item. for price in prices reads better than for p in x.
  • Give the new list a meaningful name too, so the next person knows what came out of the factory.

🧩 What You’ve Learned

  • βœ… A list comprehension builds a new list from a sequence you already have, all in one clean line.
  • βœ… The basic shape is [expression for item in sequence], which does the same job as an empty list plus a for loop plus append.
  • βœ… You can read any comprehension back to front. Find the for part first, then the expression.
  • βœ… Adding if condition at the end filters the items, so only the ones that pass the test get in.
  • βœ… You can transform and filter at the same time, like squaring only the even numbers.
  • βœ… Keep comprehensions simple and readable. When the logic gets heavy, a normal loop is the better choice.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What does [n * 2 for n in nums] do?

    Why: The expression n * 2 runs for each n in nums, producing a brand new list of doubled values.

  2. 2

    Where does the filter condition go in a list comprehension?

    Why: For filtering, the if condition is written at the end: [x for x in nums if x > 0].

  3. 3

    Given nums = [4, -2, 7, -9], what does [x for x in nums if x > 0] produce?

    Why: The if x > 0 filter keeps only the positive numbers, and the expression x leaves them unchanged.

  4. 4

    When is a regular for loop a better choice than a comprehension?

    Why: If a comprehension turns into a confusing wall of nested loops and conditions, a plain loop is clearer.

πŸš€ What’s Next?

You can now squeeze a whole loop into one clean line. Next we look at lists that hold other lists inside them, which opens up grids, tables, and more.

Nested Lists

Share & Connect