Python List Comprehension: Syntax, if-else, Dict and Set Forms
Learn Python list comprehension step by step: map and filter in one line, if-else inside, dict and set comprehensions, nested loops and when to use a loop.
Picture a billing clerk at a clothing store on MG Road at closing time. She has a register of 200 bills and the manager wants a separate sheet with just the amounts above Rs 2,000, each with 18% GST added. She goes down the register line by line: skip, skip, copy and add tax, skip, copy and add tax.
That routine has three parts: go through every bill, keep only the ones over 2,000, and write down a changed version. In Python you could write it as a four-line loop with an empty list and append(). Or you could say all three parts in a single line.
That single line is a list comprehension. "Go through every bill" is the for clause, "keep only the ones over 2,000" is the if clause, and "add tax" is the expression at the front.
A Python list comprehension is a compact expression that creates a new list by applying an expression to each item of an iterable, optionally keeping only the items that satisfy a condition.
This article continues from Python dictionaries and assumes you are comfortable with the for loop. Everything here is standard Python 3.12+.
What is list comprehension in Python?
Start with the loop you already know, then fold it into one line. Both versions below produce the same list.
bills = [1450, 2300, 980, 5200, 2050, 1999]
# Loop version
with_gst = []
for amount in bills:
if amount > 2000:
with_gst.append(round(amount * 1.18))
print(with_gst)
# Comprehension version
with_gst = [round(amount * 1.18) for amount in bills if amount > 2000]
print(with_gst)The comprehension moves the appended expression to the front; the for and if clauses keep their order.
Read a comprehension from the for outwards: "for each amount in bills, if amount > 2000, give me round(amount * 1.18)". The square brackets tell Python to collect the results into a list.
The comprehension is not just shorter. It also signals intent: anyone reading it knows at a glance that a new list is being built and nothing else is happening.
Transforming every item (map)
Without an if, a comprehension transforms every item and returns a list of the same length. This is the most common use in data cleaning.
names = [" ravi JAIN", "NEHA rao ", "asha verma"]
clean = [" ".join(n.split()).title() for n in names]
print(clean)
prices_usd = [12.5, 8.0, 30.25]
prices_inr = [round(p * 84.2, 2) for p in prices_usd] # assumed rate
print(prices_inr)
codes = ["sku-101", "sku-102"]
print([c.upper().replace("-", "_") for c in codes])
print([len(n) for n in clean])The expression at the front can be anything that produces a value: arithmetic, a string method chain, a function call or even a tuple. The string cleaning idioms come from the strings tutorial.
Filtering with if (and where if-else goes)
Here is the part that trips up nearly everyone. A comprehension can contain if in two different places, and they do different jobs.
A trailing if removes items, so the list can get shorter; an if-else at the front keeps every item and picks one of two values.
| Pattern | Position | Effect | Output length |
|---|---|---|---|
[x for x in data if cond] |
After the for |
Keeps only items where cond is true |
Same or shorter |
[a if cond else b for x in data] |
Before the for |
Chooses a value for every item | Always the same |
scores = [72, 45, 88, 39, 91, 60]
passed = [s for s in scores if s >= 50] # filter
labels = ["pass" if s >= 50 else "fail" for s in scores] # choose
capped = [min(s, 90) for s in scores] # transform only
print(passed)
print(labels)
print(capped)
# Both together: filter first, then choose
grades = ["A" if s >= 85 else "B" for s in scores if s >= 50]
print(grades)The front a if cond else b is Python's conditional expression, the one-line version of the if-else statement. It always needs the else. Writing [x for x in data if cond else 0] is a SyntaxError, because a trailing if can only filter.
You can also stack several conditions with and and or in the trailing if, such as if amount > 2000 and city == "Indore".
Quick check
What does [n * 2 for n in [1, 2, 3, 4] if n % 2 == 0] return?
The filter keeps only the even numbers 2 and 4, then each is doubled.
Quick check
Which line correctly replaces negative values with 0 and keeps all items?
An if-else that chooses a value must go before the for. A trailing if only filters, so the third option drops items.
Dict and set comprehensions
Swap the square brackets for curly braces and you get two more forms. A colon between two expressions makes a dictionary; a single expression makes a set.
products = ["toor dal", "sugar", "ghee", "salt"]
prices = [160, 46, 610, 22]
price_of = {p: r for p, r in zip(products, prices)} # dict
print(price_of)
expensive = {p: r for p, r in price_of.items() if r > 100} # filter a dict
print(expensive)
with_gst = {p: round(r * 1.05) for p, r in price_of.items()} # transform values
print(with_gst)
cities = ["Indore", "indore ", "Bhopal", "INDORE", "Ujjain"]
print(sorted({c.strip().title() for c in cities})) # set: unique, cleaned
by_price = {r: p for p, r in price_of.items()} # invert keys and values
print(by_price[46])Dict comprehensions are perfect for re-keying data, filtering a dictionary and applying a change to every value. Inverting a dictionary, as on the last line, only works safely when the values are unique; otherwise later keys overwrite earlier ones.
Set comprehensions combine cleaning with de-duplication, which the sets article explains in detail.
What about tuple comprehension?
There is no tuple comprehension. Round brackets around a comprehension create a generator expression, which produces items lazily, one at a time, instead of building the whole collection in memory. Wrap it in tuple() if you need a tuple. Generators get their own article in Python generators.
bills = [1450, 2300, 980, 5200]
gen = (b * 1.18 for b in bills)
print(type(gen).__name__)
print(round(sum(b * 1.18 for b in bills))) # no extra brackets needed inside a call
print(tuple(b for b in bills if b > 2000))Passing a generator expression straight to sum(), max() or any() is a neat habit: it avoids creating a list you only use once.
Nested loops and flattening
A comprehension can contain more than one for. The clauses run left to right, in the same order as nested loops would.
weekly = [[120, 98], [143, 110, 87], [165]] # bills per week
flat = [amount for week in weekly for amount in week]
print(flat, "total:", sum(flat))
stores = ["Rajwada", "Palasia"]
months = ["Oct", "Nov"]
pairs = [(s, m) for s in stores for m in months]
print(pairs)
table = [[r * c for c in range(1, 4)] for r in range(1, 4)] # nested result
print(table)Read [amount for week in weekly for amount in week] as: "for each week, for each amount in that week, take the amount". The outer loop comes first. That is the opposite of what many people guess, so write the loop version first if you are unsure.
The last example is different: a comprehension inside the expression of another one builds a list of lists, like a small grid.
When not to use a comprehension
Comprehensions are for building collections. They become a burden when they get clever.
- More than two
forclauses or several conditions. Readers have to decode it. A plain loop with named steps is kinder. - Side effects only.
[print(x) for x in items]builds a useless list ofNones. Use a normal loop. - Error handling. You cannot put
try/exceptinside a comprehension. Move the risky part into a small function, as shown in Python functions, and call that function in the comprehension. - Huge data you only scan once. Use a generator expression so you do not hold everything in memory.
Common mistakes with list comprehension
- Putting
elseon the filter.[x for x in d if x > 0 else 0]is invalid. Move the condition to the front:[x if x > 0 else 0 for x in d]. - Nested
forclauses in the wrong order. The outer loop is written first. - Expecting a tuple from round brackets.
(x for x in d)is a generator, not a tuple. - Overwriting keys in a dict comprehension. Duplicate keys keep only the last value, so counts silently drop.
- Reusing the loop variable name. The variable in a comprehension does not leak out, so
xafter[x for x in d]still has its old value, or is undefined. Do not rely on it.
Key takeaways
[expr for item in iterable if cond]builds a list in one readable expression.- A trailing
iffilters; a fronta if cond else bchooses a value for every item. {k: v for ...}builds a dict and{x for ...}builds a set.- Round brackets make a generator expression, ideal inside
sum(),max()andany(). - Multiple
forclauses run left to right, outer loop first. - When a comprehension needs a comment to be understood, write a loop instead.
Next, learn how to put lists and dictionaries in order with sorting in Python.
FAQ
Is list comprehension faster than a for loop in Python?
Usually yes, by a modest margin, because the comprehension avoids looking up and calling append() for every item. The gap depends on the work done per item and shrinks when that work is heavy. Readability matters more than this gap, so choose a comprehension when it is clearer, not only for speed.
Can you use if-else in a list comprehension?
Yes, but the position matters. Put a conditional expression before the for to choose between two values, as in ["pass" if s >= 50 else "fail" for s in scores]. A trailing if after the for only filters items and cannot take an else.
What is dict comprehension in Python?
A dict comprehension builds a dictionary in one expression using {key_expr: value_expr for item in iterable}. For example, {p: round(r * 1.05) for p, r in prices.items()} adds 5% to every price. It can also filter with a trailing if, such as keeping only prices above 100.
Does Python have tuple comprehension?
No. Writing a comprehension inside round brackets creates a generator expression, which yields values lazily instead of building a tuple. To get a tuple, pass the generator to the constructor: tuple(x * 2 for x in data). This is a common interview question for that reason.
Where can I practise Python comprehensions for data analytics in Indore?
You can try comprehension puzzles on Debugshala Test, the free practice platform. For guided learning, a data analytics course in Indore that drills Python daily runs at Debugshala's Old Palasia campus, in English and Hindi, with a free demo class first.
From the team behind this site
Go further with the Data Analytics Course at Debugshala
These tutorials are written by Debugshala, a training and placement institute at Old Palasia, Indore. The classroom course adds live mentoring, real projects and interview preparation.
- Offline classes at Old Palasia, Indore
- Free demo class before you pay
- Non-IT, fresher and year-gap friendly
- Placement assistance
700+ students placed · 200+ hiring partners · 4.9★ Google rating