Comprehensions
A very common job in programming is "take this list, do something to each item, and keep the results in a new list". You can do it with a for loop and append(), but Python has a shorter, clearer way called a comprehension.
In this lesson you will turn loops into list comprehensions, filter items with if, choose values with if and else, build dictionaries and sets the same way, flatten nested lists, and learn when a plain loop is the better choice.
From a loop to a list comprehension
Here is a loop that adds 18% GST to some prices, followed by the same job as a comprehension:
prices = [100, 250, 1299]
with_gst = []
for p in prices:
with_gst.append(round(p * 1.18, 2))
print(with_gst)
with_gst = [round(p * 1.18, 2) for p in prices]
print(with_gst)[118.0, 295.0, 1532.82] [118.0, 295.0, 1532.82]
Read the comprehension from the middle: "for each p in prices, give me round(p * 1.18, 2)". The square brackets mean the result is a new list. The shape is always:
[expression for item in iterable]The comprehension is one line instead of three, and it says what you want (a list of prices with GST) rather than how to build it step by step.
Filtering with if
Add if condition at the end to keep only some items:
marks = {"Aarav": 72, "Priya": 28, "Kabir": 91, "Meera": 31, "Rohan": 55}
passed = [name for name, score in marks.items() if score >= 33]
print(passed)
words = ["Rohtak", "", "Jaipur", " ", "Pune"]
clean = [w for w in words if w.strip()]
print(clean)['Aarav', 'Kabir', 'Rohan'] ['Rohtak', 'Jaipur', 'Pune']
The first comprehension loops over a dictionary's pairs (see Dictionaries) and keeps the names of students who passed. The second uses truthiness: w.strip() is an empty, falsy string for blank entries, so they are dropped.
Choosing a value with if and else
To change every item rather than drop some, put a conditional expression (from if, elif & else) at the front:
marks = [72, 28, 91, 31]
results = ["Pass" if m >= 33 else "Fail" for m in marks]
print(results)
capped = [min(m, 90) for m in marks]
print(capped)['Pass', 'Fail', 'Pass', 'Fail'] [72, 28, 90, 31]
Remember the difference by position. An if at the end filters: fewer items come out. An if ... else ... at the front chooses a value: the same number of items comes out. [x for x in items if x > 0 else 0] is a SyntaxError, because else cannot go at the end.
Dict and set comprehensions
Use curly braces with key: value to build a dictionary, or curly braces with a single expression to build a set.
cities = ["Kochi", "Lucknow", "Pune", "Jaipur"]
lengths = {city: len(city) for city in cities}
print(lengths)
initials = {city[0] for city in cities}
print(sorted(initials))
prices = {"tea": 20, "coffee": 30, "lassi": 50}
discounted = {item: p * 0.9 for item, p in prices.items() if p > 25}
print(discounted){'Kochi': 5, 'Lucknow': 7, 'Pune': 4, 'Jaipur': 6}
['J', 'K', 'L', 'P']
{'coffee': 27.0, 'lassi': 45.0}A set keeps only unique values, so the duplicate initial is stored once. Sets have no fixed order, so the example sorts them before printing. You will learn sets in Sets.
Generator expressions
If you only want to feed the results into a function such as sum(), max() or any(), leave out the brackets. This is a generator expression: it produces the values one at a time without building a whole list in memory.
cart = [("rice", 2, 64), ("oil", 1, 215), ("tea", 3, 120)]
total = sum(qty * price for name, qty, price in cart)
print("Total: ₹", total)
print(any(price > 200 for name, qty, price in cart))Total: ₹ 703 True
any() answers "is at least one value true?" and stops at the first one it finds. You will learn how generators work in Iterators & Generators.
Nested loops in a comprehension
A comprehension can have more than one for. They run in the same order as nested loops would, outer first:
classes = [["Aarav", "Isha"], ["Kabir"], ["Meera", "Rohan", "Farhan"]]
all_students = [name for group in classes for name in group]
print(all_students)
seats = [f"{row}{n}" for row in "AB" for n in range(1, 4)]
print(seats)['Aarav', 'Isha', 'Kabir', 'Meera', 'Rohan', 'Farhan'] ['A1', 'A2', 'A3', 'B1', 'B2', 'B3']
The first line flattens a list of lists into one list. Read it as two loops: "for each group in classes, for each name in group, give me name". If a comprehension needs more than two for parts or a long condition, write a normal loop instead. Readable code beats short code.
Common mistakes
- Putting
elseat the end.[x for x in items if x else 0]is invalid. Move it to the front:[x if x else 0 for x in items]. - Using a comprehension only for its side effects.
[print(x) for x in items]builds a useless list ofNonevalues. Use a normalforloop when you are not collecting results. - Writing a huge one-liner. Three nested
forparts with conditions are hard to read. Break it into a loop. - Getting nested
fororder backwards. Write theforparts in the same order as nested loops: outer first.
Key points
[expression for item in iterable]builds a new list from any iterable.ifat the end filters items;a if cond else bat the front chooses a value.{k: v for ...}builds a dict and{x for ...}builds a set.- Leave out the brackets inside
sum(),any()ormax()to use a generator expression. - Several
forparts run like nested loops, outer first. - Python 3.15 allows
*and**unpacking inside comprehensions.
Exercise
A tuition centre in Pune stores fees as fees = {"Aarav": 4500, "Isha": 0, "Kabir": 3800, "Meera": 0, "Rohan": 5200}, where 0 means not yet paid. Using comprehensions, make a list of the names of students who have not paid, a dictionary of only the paid fees with a 10% early-payment discount applied, and the total collected (after discount) using a generator expression.
Show solution
fees = {"Aarav": 4500, "Isha": 0, "Kabir": 3800, "Meera": 0, "Rohan": 5200}
unpaid = [name for name, fee in fees.items() if fee == 0]
paid = {name: fee * 0.9 for name, fee in fees.items() if fee > 0}
total = sum(amount for amount in paid.values())
print(unpaid)
print(paid)
print(f"Collected: ₹{total:,.2f}")['Isha', 'Meera']
{'Aarav': 4050.0, 'Kabir': 3420.0, 'Rohan': 4680.0}
Collected: ₹12,150.00Both comprehensions loop over fees.items() and filter with if at the end. sum(paid.values()) would also work; the generator expression shows the pattern you can use when you need to calculate something per item.
Quick Quiz
1. What does [n * 2 for n in range(4)] produce?
range(4) gives 0 to 3, and each value is doubled.
2. Which comprehension keeps only the even numbers in nums?
A filtering if goes at the end of the comprehension.
3. What kind of object does {c: len(c) for c in ["Pune", "Kochi"]} create?
Curly braces with key: value make a dict comprehension.
4. Why is sum(x * x for x in nums) written without square brackets?
Without brackets, values are produced one at a time and passed straight to sum().
Learn Python with a mentor
Free lessons get you started. Our Python Programming training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
