any and all answer two common questions in one word:

  • any(iterable) — is at least one item truthy?
  • all(iterable) — is every item truthy?

Both return a bool.

any

print(any([False, False, True]))    # True
print(any([False, False, False]))   # False
print(any([]))                       # False (no items → none are true)

print(any([0, "", None, 7]))         # True (7 is truthy)

any is short-circuit: it stops the moment it finds a truthy item.

all

print(all([True, True, True]))       # True
print(all([True, False, True]))      # False
print(all([]))                        # True (vacuously — no items to fail)

print(all([1, "hello", 3.14]))       # True (all truthy)
print(all([1, "", 3.14]))            # False ("" is falsy)

all is also short-circuit: it stops the moment it finds a falsy item.

The empty-list result surprises people. By convention, any([]) is False and all([]) is True — these match mathematical “there exists” and “for all” with no items.

With a generator expression — the real power

any and all are most useful with a generator that produces booleans:

nums: list[int] = [4, 6, 8, 10, 12]

print(all(n % 2 == 0 for n in nums))     # True — all even
print(any(n > 10 for n in nums))         # True — at least one above 10
print(any(n < 0 for n in nums))          # False — none are negative

Compare to the wordier alternative:

# clunky
all_even: bool = True
for n in nums:
    if n % 2 != 0:
        all_even = False
        break
print(all_even)

# clean
print(all(n % 2 == 0 for n in nums))

Same result. One-liner reads like a sentence.

Common patterns

A few patterns you’ll write again and again:

Validate input

def is_valid_phone(text: str) -> bool:
    return len(text) == 10 and all(c.isdigit() for c in text)

Check a structure has all required fields

required: list[str] = ["name", "email", "age"]

def has_required_fields(record: dict[str, str]) -> bool:
    return all(field in record for field in required)

Check for any failures

results: list[dict[str, str]] = [...]

if any(r["status"] == "error" for r in results):
    print("Some operations failed")

Check no failures

if not any(r["status"] == "error" for r in results):
    print("All clean")

# or equivalently
if all(r["status"] != "error" for r in results):
    print("All clean")

Pitfall — accidentally passing booleans

A subtle bug: passing a single boolean instead of a list of them.

# wrong — passes a single bool, not iterable
all(True)   # TypeError: 'bool' object is not iterable

any and all need an iterable. If you only have one value, just use it directly.

Summary of Section 7

You now know the functional toolkit:

  • map — transform every item (often replaced by a comprehension)
  • filter — keep items that pass a test (also often replaced by a comprehension)
  • zip — walk two or more iterables together
  • enumerate — loop with the index
  • sorted — sort anything, by any key
  • any / all — quick yes/no questions over a collection

Most of these you’ll use daily. They turn long loops into single readable lines.

What’s next

Section 8: Iterators and Generators — the protocol that lets you produce values lazily, one at a time. Essential for data pipelines.

Toggle theme (T)