filter()
Keep items where a predicate returns truthy — lazily. The functional cousin of a filtered comprehension.
Common call
list(filter(None, items))
Returns
a lazy filter iterator — wrap in list() to materialize
Replaces
a comprehension: `[x for x in items if pred(x)]`
Watch out
None as predicate means "keep truthy items"; iterator is consumed on first pass
filter(predicatepredicate — A function returning True/False (or truthy/falsy) per item. Special case: None means "keep items that are themselves truthy".type: callable | None · required, iterableiterable — The source items. Any iterable works.type: iterable · required)
→ filter
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| predicate | callable | None | yes | A function returning True/False (or truthy/falsy) per item. Special case: None means "keep items that are themselves truthy". |
| iterable | iterable | yes | The source items. Any iterable works. |
Return value
filter — A lazy iterator yielding items where predicate(item) is truthy. If predicate is None, keeps items that are TRUTHY themselves.
Common patterns
Keep truthy items only
The special-case `filter(None, iterable)` — the idiomatic drop-falsy pattern.
active = list(filter(None, items)) # drops 0, "", [], None, False
Named predicate
Use the unbound method — same result as a comprehension with a call.
digits = list(filter(str.isdigit, tokens))
Chain with map for a pipeline
Lazy: no intermediate list is built.
result = list(map(int, filter(str.isdigit, tokens)))
When a comprehension reads better
For non-trivial predicates, a comprehension is often clearer.
# instead of: filter(lambda x: x % 2 == 0 and x > 0, xs) positives_even = [x for x in xs if x % 2 == 0 and x > 0]
Examples
1. Keep positive
list(filter(lambda x: x > 0, [-1, 0, 1, 2]))
Returns
[1, 2]2. Predicate is None
list(filter(None, [0, 1, "", "hi", None]))
Returns
[1, "hi"] # truthy only3. String method as pred
list(filter(str.isdigit, ["a", "1", "b", "2"]))
Returns
["1", "2"]4. Empty gives empty
list(filter(None, []))
Returns
[]5. All match
list(filter(lambda x: x > 0, [1, 2, 3]))
Returns
[1, 2, 3]6. None match
list(filter(lambda x: x > 100, [1, 2, 3]))
Returns
[]Pitfalls
1. filter() returns an ITERATOR, not a list
In Python 2 it returned a list; Python 3 made it lazy. Printing a filter object shows `<filter object at ...>` — call list() to materialize.
Printed iterator
print(filter(None, [1, 0, 2]))
<filter object at 0x...>
Wrap in list
print(list(filter(None, [1, 0, 2])))
[1, 2]
2. Iterator is CONSUMED on first pass
Once iterated, a filter iterator is exhausted. Trying to reuse it gives an empty iterator.
Empty second time
f = filter(None, items) list(f) # results list(f) # []
exhausted
Materialize once
result = list(filter(None, items))
reusable
3. predicate=None means "keep truthy", NOT "keep everything"
Newcomer trap. `filter(None, items)` does NOT return items untouched — it drops every falsy item (0, "", [], None, False). If you truly want "keep everything", you did not need filter at all.
Assumed identity
list(filter(None, [0, 1, 2]))
[1, 2] # 0 dropped
Use lambda
list(filter(lambda x: True, [0, 1, 2]))
[0, 1, 2] # actually keep all
4. A comprehension usually reads better than filter+lambda
filter(lambda x: pred, items) is functionally identical to [x for x in items if pred] but the comprehension is more Pythonic. Reach for filter when the predicate is already named.
filter + lambda
list(filter(lambda x: x > 0, xs))
works, but stiff
Comprehension
[x for x in xs if x > 0]
idiomatic
When to use
Use it
- Applying a NAMED predicate — `filter(str.isdigit, ...)`
- The special `filter(None, iterable)` to drop falsy items
- Lazy pipelines chained with map()
- Interop with functional-style libraries expecting iterators
Reach for something else
- `filter(lambda x: ...` — use a comprehension instead
- Need to iterate multiple times → wrap in list()
- Rich filtering (multiple predicates) → comprehension with `and`
- Filter AND modify → chain with map, or use a comprehension
Notes
Complexity
O(1) to construct; O(n) to iterate; per-item cost is predicate()
Return
A filter iterator — lazy
CPython impl
Python/bltinmodule.c :: builtin_filter
Memory
O(1) — no intermediate list is built
Thread-safe
Depends on predicate and the underlying iterable
FAQ
Behaviorally almost identical, but filter is LAZY (returns an iterator) while a comprehension with `if` is EAGER (returns a list). For a named predicate, filter is compact. For an inline test, the comprehension reads better.
History
1.0
filter() has been a builtin since Python 1.0 — returned a list.
3.0
Return type changed from list to lazy iterator.