I ran into this problem when I had a list of user records with some missing fields, and I needed to extract only the valid ones before processing. Writing a loop felt verbose for something this simple. That’s when I reached for Python’s filter() function.

The article covers how filter() works, its two required arguments, how to use it with lambda and named functions, what happens when you pass None as the predicate, and how it compares to list comprehensions. By the end, you’ll know exactly when to reach for filter() and how to avoid the most common mistakes.

TLDR

  • filter(predicate, iterable) returns a filter object – wrap it in list() to get a list
  • The predicate must return True (keep) or False (discard) for each element
  • Pass None as predicate to keep only truthy values – useful for removing empty strings, zeros, and None from data
  • The lambda function syntax is the most common way to define inline predicates
  • For simple keep/discard logic, a list comprehension is often more readable – filter() shines when the predicate logic is complex or reused

What is filter() in Python?

filter() is a built-in Python function that extracts elements from an iterable based on a predicate – a function that returns True or False. It evaluates the predicate on each item and yields only those for which the predicate returns True. Unlike a loop, filter() does not modify the original iterable and produces a lazy iterator that can be converted to a list, tuple, or set.

filter() Syntax and Arguments

The function takes exactly two arguments:

filter_object = filter(predicate, iterable)

The predicate is any callable that accepts one argument and returns a boolean. It can be a function reference, a lambda expression, or None. The iterable is any Python object that supports iteration – lists, tuples, strings, dictionaries, sets, or generator objects.

The return value is a filter object, which is an iterator. It is not a list. Calling list() on it materializes all filtered elements, or you can iterate over it directly with a for loop.

Using filter() with Lambda and Named Functions

Here is a basic example that separates even and odd numbers from a list. The lambda predicate checks the modulo condition, and the function reference example shows the equivalent using a named function.

a = [1, 2, 3, 4, 5]

filter_obj_even = filter(lambda x: x % 2 == 0, a)
print(type(filter_obj_even))
print('Even numbers:', list(filter_obj_even))

def odd(num):
    return (num % 2) != 0

filter_obj_odd = filter(odd, a)
print('Odd numbers:', list(filter_obj_odd))


Even numbers: [2, 4]
Odd numbers: [1, 3, 5]

The type() call confirms that filter() returns a filter object, not a list. The lambda expression lambda x: x % 2 == 0 is the most compact way to express the predicate inline. For more complex logic that needs to be reused across multiple filter() calls, a named function like odd() is cleaner.

You can iterate over a filter object directly without converting it to a list, which is memory-efficient for large datasets.

def odd(num):
    return (num % 2) != 0

a = [1, 2, 3, 4, 5]
filter_obj_odd = filter(odd, a)

for item in filter_obj_odd:
    print(item)

filter() with None as Predicate

Passing None as the predicate uses each element’s inherent boolean value for filtering. Python treats 0, 0.0, None, empty strings '', empty lists [], and empty dicts {} as falsy. All other values are truthy. This makes filter(None, iterable) a convenient way to strip falsy values from data without writing an explicit predicate.

a = [0, 1, 'Hello', '', [], [1, 2, 3], 0.1, 0.0]
print(list(filter(None, a)))

[1, 'Hello', [1, 2, 3], 0.1]

The 0, '', [], and 0.0 entries are removed because they are falsy in Python. This pattern is especially useful when cleaning data loaded from external sources where empty or zero values need to be removed before processing.

FAQ

Q: What is the difference between filter() and a list comprehension?

Both evaluate a condition on each element and return a filtered collection. filter() returns a lazy iterator and is a functional programming construct. A list comprehension like [x for x in iterable if condition] produces a list eagerly and is generally more readable for simple keep-or-discard operations. Use filter() when the predicate is complex, needs to be reused, or when lazy evaluation matters for memory efficiency.

Q: Does filter() modify the original list?

No. filter() does not mutate the original iterable. It returns a new filter iterator. The original list remains unchanged.

Q: Can filter() work with dictionaries and sets?

Yes. Any iterable works. For dictionaries, the predicate operates on keys by default. For sets, it operates on individual elements the same way it works with lists.

Q: What happens if the predicate returns a non-boolean value?

Python’s bool() is called implicitly on the return value. Any falsy value (0, None, '', [], etc.) acts as False, and any truthy value acts as True. This means filter() can accidentally keep elements if the predicate is not careful about return types.

Q: How is filter() different from map()?

map() transforms each element – it applies a function to every item and yields the results. filter() makes a binary keep-or-discard decision – it yields elements only when the predicate returns True. The two functions are often used together: map() to transform, then filter() to narrow down the results.

I use filter() whenever I need to narrow down a dataset before applying transformations. The combination of filter() and map() covers most of the functional-style data processing I write in Python.

Share.
Leave A Reply