The built-in filter takes a function and an iterable, and yields only the items for which the function returns a true value. In Python 3 it returns an iterator, not a list.
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = filter(lambda x: x % 2 == 0, numbers)
print(list(even_numbers))You should see [2, 4, 6]. That is the core idea: test each element, keep those where the predicate is true.
If you only need a single yes/no over a predicate, any() is often simpler than fully consuming a filter iterator—see Python any() and all() for that pattern.
Tested on: Python 3.13.3; kernel 6.14.0-37-generic.
What does filter() do in Python?
filter(function, iterable) walks iterable one item at a time. For each item, Python calls function(item) (or treats the item as true/false when function is None). If the result is true, the item is yielded; otherwise it is skipped. The original iterable is not replaced—filter produces a new stream of references to the same objects unless your function copies or mutates them.
Python filter() syntax
filter(function, iterable)function: a callable taking one argument, orNone(seefilter(None, ...)below).iterable: any iterable (list, tuple, string, dict views, file lines, custom objects, and so on).
The return type in Python 3 is a filter iterator object.
Why filter() returns a filter object
Python 3’s filter() constructs an iterator—you will see something like <filter object at 0x...> if you print the result without converting it. That design saves memory: values are computed on demand as you iterate, instead of building a whole list up front.
Convert filter object to list
Wrap the iterator in list() when you need a concrete list (printing, indexing twice, or passing to APIs that expect a sequence).
nums = [1, 2, 3]
positive = filter(lambda x: x > 0, nums)
print(list(positive))You should see [1, 2, 3].
Filter a list using a normal function
Named predicates stay readable when the condition grows beyond a one-liner.
def is_even(n):
return n % 2 == 0
numbers = [1, 2, 3, 4, 5, 6]
print(list(filter(is_even, numbers)))You should see [2, 4, 6]. For more on sequences, see the Python list guide.
Filter a list using lambda
For small predicates, a lambda keeps the call site compact.
numbers = [1, 2, 3, 4, 5, 6]
print(list(filter(lambda x: x % 2 == 1, numbers)))You should see [1, 3, 5].
Filter strings using filter()
Strings are iterable over characters. Here we keep only ASCII letters.
text = "a1b2c"
print("".join(filter(str.isalpha, text)))You should see abc.
Filter a dictionary using filter()
dict.items() yields (key, value) pairs; filter them, then pass the iterator to dict(...).
scores = {"Alice": 85, "Bob": 40, "Charlie": 72}
passed = dict(filter(lambda item: item[1] >= 50, scores.items()))
print(passed)You should see {'Alice': 85, 'Charlie': 72}. For dict basics, see Python dictionary example.
Filter objects using filter()
Use attributes in the predicate when filtering a list of instances.
class User:
def __init__(self, name, active):
self.name = name
self.active = active
users = [
User("Alice", True),
User("Bob", False),
User("Charlie", True),
]
active_users = list(filter(lambda user: user.active, users))
print([u.name for u in active_users])You should see ['Alice', 'Charlie'].
Use filter(None, iterable)
If the first argument is None, Python uses the identity: items that are falsy (False, None, numeric zero, empty strings, empty containers, and so on) are dropped; truthy values are kept.
values = [0, 1, "", "hello", None, [], [1, 2], False, True]
result = list(filter(None, values))
print(result)You should see [1, 'hello', [1, 2], True].
filter() vs list comprehension
List comprehensions put the expression and condition in one place; many teams find them easier to read for simple filters.
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = [x for x in numbers if x % 2 == 0]
print(even_numbers)You should see [2, 4, 6]. Prefer filter when you already have a reusable function or want lazy evaluation without building a list until you iterate. Prefer a comprehension when the logic is short and local. A generator expression (x for x in numbers if x % 2 == 0) is similarly lazy like filter if you only need iteration once. See list comprehension examples for side-by-side patterns.
filter() with map()
You can chain filter then map when you want to transform the kept items (both are lazy until consumed). See Python map() for transform-only pipelines.
nums = [1, 2, 3, 4]
labels = list(map(str, filter(lambda x: x % 2 == 0, nums)))
print(labels)You should see ['2', '4'].
Common mistakes with filter()
These bullets are reminders; you do not need a separate runnable block for every one, because list(), filter(None, ...), and dict filtering are already shown above. The snippets below only illustrate mistakes that are easy to misread in isolation.
- Forgetting that
filter(...)is an iterator and printing it raw instead of wrapping withlist()or iterating in a loop. - Writing
filter(some_func(), iterable)instead offilter(some_func, iterable)—you must pass the function object, not call it in place unless it returns a callable. - Expecting
filterto mutate the original list—it never does by itself. - Using
filterwith a huge lambda when a list comprehension would be clearer to the next reader. - Misunderstanding
filter(None, ...)as “removeNoneonly”—it removes all falsy values. - Iterating the same
filterobject twice: the iterator is exhausted after the first pass; callfilteragain or storelist(...)if you need multiple walks. - Overly complex lambdas—switch to a named
deffor readability.
def is_positive(x):
return x > 0
nums = [-1, 2, 3]
f = filter(is_positive, nums)
print(f) # shows a filter object, not the values
print(list(f))
# filter(is_positive(), nums) # wrong: TypeError—calls the function before filter runsYou should see a line starting with <filter object and then [2, 3].
nums = [1, 2, 3]
f = filter(lambda x: x % 2 == 0, nums)
print(list(f))
print(list(f)) # already exhaustedYou should see [2] then [].
Python filter() quick reference table
| Need | Pattern |
|---|---|
| Basic filter | filter(pred, iterable) |
| Materialize | list(filter(...)) |
| Keep truthy only | filter(None, iterable) |
| Dict by value | dict(filter(lambda kv: ..., d.items())) |
| Lazy + transform | map(fn, filter(pred, iterable)) |
| Readable inline | [x for x in items if cond] |
Summary
filter(function, iterable) returns a Python 3 iterator that yields items where function(item) is true, or where the item is truthy when function is None. Convert with list() when you need a list, reuse predicates as normal functions when logic grows, and reach for comprehensions when the condition is short and clarity beats laziness. Remember iterators are single-use unless you rebuild them.
References
filter()built-in- Functional programming HOWTO
Frequently Asked Questions
What does Python filter() return?
In Python 3, filter() returns an iterator (a filter object); consume it in a loop, pass it to list(), or walk it once—materialize with list() when you need all values in memory.
What is the difference between filter() and list comprehension?
filter() shines when you already have a named predicate function or want a lazy iterator; list comprehensions are often clearer for short inline conditions on simple data.
What does filter(None, iterable) do?
With function set to None, filter uses the identity and drops items that are false in a boolean context (falsy values such as 0, empty containers, None, False).
Does filter() change the original list?
No—it builds a new iterator over the iterable; the source list or other collection is left unchanged unless your predicate mutates it as a side effect.
Why is my second list(filter(...)) empty?
filter iterators are single-pass; after you exhaust them once, you must call filter() again or store the list result if you need to iterate multiple times.

