How to Build a Chainable Filter Helper in Python
A beginner-friendly dataclass helper that chains filters, uniqueness, and slicing on any sequence, returning a plain list at the end.
Python code
42 linesfrom dataclasses import dataclass
from typing import Callable, Iterator, Sequence, TypeVar
T = TypeVar("T")
@dataclass
class FilterAssistant:
"""Beginner-friendly helper to filter any collection."""
data: Sequence[T]
def where(self, predicate: Callable[[T], bool]) -> "FilterAssistant":
return FilterAssistant([item for item in self.data if predicate(item)])
def first_n(self, n: int) -> "FilterAssistant":
return FilterAssistant(self.data[:n])
def unique(self) -> "FilterAssistant":
seen = set()
result = []
for item in self.data:
if item not in seen:
seen.add(item)
result.append(item)
return FilterAssistant(result)
def apply(self) -> list:
return list(self.data)
if __name__ == "__main__":
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 3, 7]
result = (
FilterAssistant(numbers)
.where(lambda x: x % 2 == 0)
.where(lambda x: x > 2)
.unique()
.first_n(3)
.apply()
)
print(result)
Output
[4, 6, 8]
How it works
This code uses a @dataclass to store the current filtered sequence, and each method returns a new FilterAssistant instance, enabling chaining. The where method applies a predicate using a list comprehension, keeping only items that satisfy the condition. unique removes duplicates while preserving order by tracking seen items in a set. first_n slices the sequence to the first n elements. The final apply method returns a plain list, making the helper easy to use in any context.
Common mistakes
- Forgetting that methods return a new FilterAssistant, not the original data
- Not using type hints, which reduces readability and maintainability
- Using a mutable default or modifying the original sequence unintentionally
Variations
- Use a generator expression in `where` to avoid creating an intermediate list
- Implement `__iter__` on the class to allow direct iteration instead of calling `apply()`
Real-world use cases
- Building a reusable data-cleaning pipeline that filters rows by multiple conditions in a Jupyter notebook.
- Creating a chainable query builder for in-memory collections in a CLI data analysis tool.
- Teaching beginners how fluent interfaces work by chaining transformations on a small dataset.
Sponsored
More from Modern tooling
- Build a Recipe Runner Mock in Python easy
- Build a Textual TUI App Skeleton in Python easy
- Configure ruff linter rules in pyproject.toml with Python easy
- Data Conversion Helper Functions in Python easy
- How to Bind and Mock structlog Context in Python medium
- How to Build a Wheel with Hatchling in Python easy
Keep learning
Related tutorials and quizzes for this topic.