Filter Function in Python

When a list of records includes entries that pass a condition and entries that do not, selecting the matches calls for a test. Python’s filter() applies a test, called a predicate, to each item and returns an iterator containing the items that pass.

I’ll show how to write that test and consume the iterator, then explain when a list comprehension is a better fit.

TL;DR

Python’s filter() calls a predicate for each item and returns an iterator containing the items whose result is truthy.

  • Call it as filter(predicate, iterable).
  • Use list() when the result must be a list.
  • Pass a named function or a short lambda as the predicate.
  • Use None only when you want to discard every falsy value.

What Does filter() Do in Python?

filter() is a built-in for selecting values from Python data.

ArgumentPurpose
functionTests one item and returns a truth value
iterableProvides the items to test

An iterable may be a list, tuple, string, or generator. A string yields one-character strings, while a generator yields whatever objects it was written to produce, so write the predicate for the actual item type.

The string tests are not identical: str.isdecimal recognizes decimal characters, while str.isdigit also accepts some digit-like characters such as superscripts.

A dictionary is iterated by key. Use values() to test only its values, or items() when the rule needs each key and value together.

Use list() for an ordered, mutable result that retains duplicates. Choose tuple() for an ordered result that will not change, or set() when unique values matter and order does not.

How to Use filter() Step by Step

This example uses a named predicate for the record flag and a short lambda for its score test.

Step 1: Write a predicate for each record

Define a predicate with one parameter, such as a named function that returns each record’s active field. Pass the function name, not a call, so filter invokes it for each input record.

def is_active(record):
    return record["active"]

Step 2: Filter the records and consume the result

Iterating over the result extracts the names without building a second list of complete record dictionaries.

records = [
    {"name": "Mina", "active": True, "score": 82},
    {"name": "Omar", "active": False, "score": 91},
    {"name": "Ravi", "active": True, "score": 74},
]

def is_active(record):
    return record["active"]

active_records = filter(is_active, records)
print([record["name"] for record in active_records])

scores = [42, 55, 61, 73, 88]
passing_scores = filter(lambda score: score >= 60, scores)
print(list(passing_scores))
print(list(filter(None, [0, 4, None, 7])))

active_names = [record["name"] for record in filter(is_active, records)]
print(active_names)
vijaykrishna@askpython:~$ python3 filter_records_demo.py
['Mina', 'Ravi']
[61, 73, 88]
[4, 7]
['Mina', 'Ravi']
Terminal output showing active record names and passing scores
Filtering records by an active flag and score condition.

The name output contains Mina and Ravi, while the score output contains the values that pass its test. The next line shows that filter(None, values) removed zero and None. The final line creates a fresh filter from records, since the first iterator has already been consumed.

Common Edge Cases When Using filter()

Input truth values matter when a zero or blank value carries meaning.

CaseSymptomFix
A zero or blank value is meaningfulfilter(None, values) drops it because it is falsy.Use a predicate that tests the intended rule.
Text includes digit-like charactersstr.isdigit() accepts some characters, such as superscripts, that str.isdecimal() excludes.Use str.isdecimal() when only decimal characters should pass.
A predicate returns a non-boolean valuePython tests that result for truth, which can obscure the intended rule.Return an explicit boolean when the rule needs to be clear.
Filtering before or after conversionText format and numeric magnitude are different tests.Check text format before conversion and numeric magnitude after conversion.
Reusing a filter resultThe iterator is consumed as you iterate over it.Create a new filter from the original iterable or store the result in a list.

Choose filter() or a comprehension

For a short list condition, use a list comprehension. filter() suits a previously defined predicate. The table compares the results, and the list comprehension guide covers its syntax.

ChoiceResultUse it when
filter(None, values)Iterator of truthy input valuesEvery falsy value should be removed
filter(predicate, values)Iterator of values accepted by the predicateThe test has a name or will be reused
[value for value in values if condition]New list built immediatelyThe condition is short and the result should be a list

Conclusion: Choose the Right Filter

For its positional-only signature and details about the built-in, see the Python filter() reference.

FAQ

These answers cover two common questions about the return value and the optional predicate.

Does filter() return a list in Python?

No. It returns a filter iterator. Call list() to create a list of all matching items, or iterate over the result directly.

What does filter(None, iterable) do?

It uses each item as its own truth test and yields the truthy items. Values such as 0, False, None, and empty strings are skipped.

Does filter() change the original iterable?

No. It yields references to matching input items without changing the iterable itself. Changes to a mutable item can still be seen through that same object.

Vijaykrishna Ram
Vijaykrishna Ram
Articles: 99