The power of list comprehensions isn't just about transforming data, it's about selecting it.
Imagine you have a list of 1,000 items, but you only care about 5 of them. In a traditional loop, you would write an if statement to check each item and decide whether to append it.
Python list comprehensions allow you to bake this "Gatekeeper Logic" directly into the syntax. This is called Filtering.
[!NOTE] Quick Rules
- Syntax:
[expression for item in list IF condition]- Position: The
ifALWAYS goes at the end.- Logic: If
True, the item is kept. IfFalse, it is discarded.
Table of Contents
- The Syntax of Filtering
- How filtering works (Visualized)
- Basic Filtering Patterns
- Conditionals Deep Dive
- Multiple Conditions (AND/OR Logic)
- Common Mistakes (The Else Trap)
- Performance Implications
- FAQ
- Test Your Knowledge (Quiz)
The Syntax of Filtering
The syntax places the condition at the very end of the comprehension.
# [ Expression Loop Filter ]
[ item for item in data if condition ]
Example:
# Keep numbers matching strict criteria
[x for x in range(10) if x > 5]
Where does the if go?
It MUST go after the for loop. If you put it before, Python thinks you are trying to do a ternary operation (If-Else), and will raise a SyntaxError because you forgot the else.
How Filtering Works (Visualized)
It helps to visualize the order of operations.
[ Source List ]
|
v
(Next Item) ---> [ Condition Check passed? ]
|
NO -------+------- YES
| |
(Discard) (Evaluate Expression)
|
[ Add to New List ]
- Iterate: Python picks the next item from the loop.
- Check: Python evaluates
condition. Is itTrue?- NO: Discard item. Jump back to Step 1.
- YES: Proceed to Step 3.
- Evaluate Expression: Calculate the result.
- Append: Add result to the new list.
Note that the Expression is only evaluated if the condition is True. This is important if your expression involves something that might crash on invalid data (like dividing by zero).
# This is safe because check happens first
[10 / x for x in [0, 1, 2] if x != 0]
Basic Filtering Patterns
Here are the most common patterns you will use daily.
1. Numeric Comparison
Filtering by value range.
scores = [55, 90, 45, 80]
passing = [s for s in scores if s >= 60]
# Result: [90, 80]
2. String Matching
Filtering text data.
files = ['idx.html', 'style.css', 'script.js']
css_files = [f for f in files if f.endswith('.css')]
# Result: ['style.css']
3. Truthiness Check (Identity)
Removing empty values (None, empty strings, 0).
data = ["Alice", "", None, "Bob"]
clean = [x for x in data if x]
# Result: ['Alice', 'Bob']
Note: if x evaluates to True for non-empty strings and non-None values.
4. Membership Testing (in)
Checking against whitelist/blacklist.
allowed_ids = [1, 2, 5]
requests = [1, 3, 5, 9]
valid = [r for r in requests if r in allowed_ids]
# Result: [1, 5]
Conditionals Deep Dive
The condition part can contain any valid Python expression that returns a boolean.
Using Function Calls
You can call a function in the filter.
def is_prime(n):
# ... implementation ...
return True
primes = [x for x in range(100) if is_prime(x)]
Warning: This function runs for every item in the list. If is_prime is slow and your list is huge, your code will crawl.
Using Methods
names = ["alice", "Bob", "charlie"]
capitals = [n for n in names if n.istitle()]
# Result: ['Bob']
Multiple Conditions (AND/OR Logic)
What if you need two checks? "Even numbers AND greater than 10"?
Method A: The Explicit and
This is the most readable way.
[x for x in range(20) if x % 2 == 0 and x > 10]
Method B: The Implicit Chain
You can technically chain filtering if statements.
[x for x in range(20) if x % 2 == 0 if x > 10]
Python treats if A if B exactly the same as if A and B. However, Method A is generally preferred because it looks like normal English.
Method C: The or Operator
For "This OR That" logic, you must use or.
# Keep if it's divisible by 2 OR 5
[x for x in range(20) if x % 2 == 0 or x % 5 == 0]
Method D: Grouping with Parentheses
If you mix and/or, always use parentheses to prevent logic errors.
# (Divisible by 2 OR 3) AND (Not 0)
[x for x in range(20) if (x % 2 == 0 or x % 3 == 0) and x != 0]
Common Mistakes (The Else Trap)
This is the #1 error beginners make with filtering.
The Mistake: Trying to add an else clause at the end.
[x for x in items if x > 0 else 0] # SYNTAX ERROR
The Reason:
- The
ifat the end is a Filter. It means "Include or Exclude". There is no "Else" concept in filtering. If you exclude it, it's gone. - If you want "Keep or Replace" (e.g., keep positive, replace negative with 0), that is a Transformation. The syntax for that is different (
if-elseat the start).
Quick Rule:
- Do you want the list to be shorter? -> Use
ifat the end. - Do you want the list to be the same length? -> Use
if-elseat the start.
Performance Implications
Filtering is generally fast, but be careful with what you put in the condition.
Fast: if x > 5 (Simple CPU op)
Slow: if x in list (Linear search)
Very Slow: if database_check(x) (Network I/O)
Optimization Tip: Use Sets for Lookup
If you are filtering items based on whether they exist in another large list, convert the lookup list to a set first.
FAQ
Q1: Can I filter based on the index?
A: Yes, but you need to use enumerate.
items = ['a', 'b', 'c', 'd']
# Keep items at even indices (0, 2)
evens = [x for i, x in enumerate(items) if i % 2 == 0]
Q2: Can I use try-except in the filter?
A: No. Expressions in comprehensions cannot contain blocks. If you need exception handling (e.g., ignoring items that fail conversion), write a helper function that returns False on error.
Q3: How do I filter a dictionary?
A: Use .items().
d = {'a': 1, 'b': 2}
# Keep items where value > 1
filtered = {k:v for k,v in d.items() if v > 1}
Test Your Knowledge
Conclusion
You are now a master of the standard list comprehension formula. You can map values, and you can filter them.
Next Steps:
- Combine them! Learn "Transformation with Logic": If-Else Guide
- Handle complexity: Nested Comprehensions