Python
list comprehension
programming tips
conditional statements
data processing

How to check if all elements of a list match a condition?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Python, the standard way to check whether every element in a list satisfies a condition is all(...). The main design question is not the syntax, but how to handle empty input, mixed types, and callers that need more than a simple True or False.

Use all With a Generator Expression

The most direct pattern is a generator expression passed to all.

python
values = [2, 4, 6, 8]
all_even = all(v % 2 == 0 for v in values)
print(all_even)

This is efficient because all short-circuits. It stops at the first failure, so expensive predicates are not evaluated unnecessarily.

Wrap Reusable Checks in a Helper

If the same style of validation appears in multiple places, wrap it in a helper so the call site reads like intent instead of plumbing.

python
1from typing import Callable, Iterable, TypeVar
2
3T = TypeVar("T")
4
5def all_match(items: Iterable[T], predicate: Callable[[T], bool]) -> bool:
6    return all(predicate(item) for item in items)
7
8print(all_match(["aa", "bb"], lambda s: len(s) == 2))
9print(all_match(["aa", "b"], lambda s: len(s) == 2))

This pattern keeps domain logic readable and makes unit testing easier.

Decide What Empty Input Means

Python defines all([]) as True. That is mathematically sensible, but it is not always what an application wants.

python
1def all_positive_non_empty(values):
2    return bool(values) and all(v > 0 for v in values)
3
4print(all_positive_non_empty([1, 2, 3]))
5print(all_positive_non_empty([]))

If a list must contain at least one element, say so directly instead of relying on readers to remember how all behaves on empty iterables.

Handle Mixed Types Deliberately

If the predicate assumes numbers, then None or a string may raise an exception. In that case, a loop can be clearer than one dense generator expression.

python
1def all_in_range(values, low, high):
2    for value in values:
3        if not isinstance(value, (int, float)):
4            return False
5        if not (low <= value <= high):
6            return False
7    return True
8
9print(all_in_range([1, 5.5, 9], 0, 10))
10print(all_in_range([1, "x", 9], 0, 10))

This style is often easier to maintain when validation has multiple steps.

Return Failure Details When Needed

A bare boolean is sometimes too weak. If the caller needs to know why validation failed, return the first bad index and value.

python
1from dataclasses import dataclass
2from typing import Any, Callable, Iterable
3
4@dataclass
5class CheckResult:
6    ok: bool
7    index: int
8    value: Any
9
10
11def first_failure(items: Iterable[Any], predicate: Callable[[Any], bool]) -> CheckResult:
12    for index, item in enumerate(items):
13        if not predicate(item):
14            return CheckResult(False, index, item)
15    return CheckResult(True, -1, None)
16
17result = first_failure([3, 6, 7, 12], lambda n: n % 3 == 0)
18print(result)

That extra detail is valuable in validation libraries, ETL jobs, and tests.

Apply the Same Pattern to Structured Data

The predicate does not have to be a tiny numeric test. It can validate dictionaries, records, or model objects.

python
1def is_valid_order(order):
2    return (
3        isinstance(order, dict)
4        and isinstance(order.get("total"), (int, float))
5        and order["total"] >= 0
6    )
7
8orders = [
9    {"id": 1, "total": 120.0},
10    {"id": 2, "total": 48.5},
11]
12
13print(all(is_valid_order(order) for order in orders))

The same all(...) pattern still works, but the predicate is now meaningful at the business level.

Common Pitfalls

The most common mistake is forgetting that all([]) returns True and accidentally accepting empty input that should fail.

Another common issue is writing predicates that raise exceptions on mixed-type data instead of returning False cleanly. Developers also sometimes compress too much logic into one generator expression when a small helper or loop would be easier to read.

Summary

  • Use all(predicate(x) for x in items) as the normal Python pattern.
  • Remember that all([]) is True, and override that if the domain requires non-empty input.
  • Prefer a loop when validation has multiple steps or type checks.
  • Return failure details when the caller needs more than a boolean.
  • Keep predicates readable, especially for structured data.

Course illustration
Course illustration

All Rights Reserved.