any and all are two small built-ins that answer two very common questions about a collection: "is at least one of these true?" and "are all of these true?". They read like English, short-circuit as soon as they have an answer, and pair beautifully with generator expressions. This lesson covers what they return, the surprising case of an empty iterable, and how to write validation checks that are both fast and readable.
Both functions take a single iterable and return a boolean. any returns True if at least one element is truthy, and False if every element is falsy. all returns True if every element is truthy, and False if at least one element is falsy.
The elements don't have to be booleans. Anything Python can evaluate for truthiness works, so you can drop in numbers, strings, lists, or objects. These values are falsy: 0, 0.0, "", None, [], {}, set(), and False. Everything else is truthy.
This is the simplest form. The real power shows up when you pair these with a generator expression that produces booleans from a richer input, which we'll get to in a moment.
Here's the one rule that trips up almost everyone the first time they meet these functions.
any([]) returning False feels intuitive. There's nothing in there, so nothing is true. Fine.
all([]) returning True is the surprise. Even with no elements, all says yes.
This is called vacuous truth. The rule for all is "every element satisfies the condition". If there are no elements, there are no elements that fail to satisfy the condition, so the rule technically holds. Python is being a strict logician here. The same idea shows up in math: a statement of the form "for every x in the empty set, P(x) holds" is always true because there's no counterexample to find.
This matters in real code. A common pattern is to validate every item in a cart:
An empty cart is reported as having all items in stock. If your business logic depends on the cart actually containing something, you have to check that separately.
The cart and ... short-circuits when the cart is empty, so all never even runs in that case. This is the safe pattern for any "must have at least one item AND every item must satisfy something" check.
You almost never call any or all on a literal list of booleans. The real use is pairing them with a generator expression that turns each element into a boolean on the fly. Generator expressions look like list comprehensions but use parentheses and produce one value at a time.
The expression price > 40 for price in prices yields False, False, False, True, False. As soon as any sees the first True, it stops and returns. We'll come back to that "stops" part below.
When the inputs are richer objects, generator expressions let you reach into them cleanly:
Two readable lines that each answer a complete business question. Without any and all, you'd write a loop with a flag variable and an early break, and the result would be longer and noisier.
Cost: Always prefer a generator expression over a list comprehension inside any and all. any([item["stock"] == 0 for item in cart]) builds the entire list first, then walks it. The generator form any(item["stock"] == 0 for item in cart) walks the cart lazily and stops at the first hit. For a 10,000-item cart where the first item is out of stock, the generator form does one check; the list-comprehension form does 10,000.
Both functions stop as soon as they can answer the question. any stops at the first truthy element. all stops at the first falsy element. This is called short-circuit evaluation, and it's the same idea you've seen with the and and or operators.
The diagram shows the decision flow. Each element is checked one at a time, and the function bails out the moment the result is decided. any wins on a truthy element; all wins on a falsy element.
You can see this clearly with a generator that prints as it yields:
any checks the Mouse, sees stock 5 (truthy but the condition == 0 is False, so it keeps going), then checks the Cable, sees stock 0 which makes the condition True, returns immediately. The Charger is never inspected. This is the whole point: you get the answer with the minimum amount of work.
The same logic applies to all, just inverted:
The Mouse passes (stock 5 > 0), the Cable fails (stock 0 > 0 is False), and all returns False without ever checking the Charger.
Cost: Short-circuiting is why these functions are cheap for huge iterables when the answer is decided early. For 1 million items where the first one fails an all check, all does one comparison and stops. The cost scales with how far in the answer is, not the total size.
These two functions cover a small number of patterns that come up constantly.
Pattern 1: "Does at least one match?"
Pattern 2: "Do all of them match?"
Pattern 3: Input validation
Pattern 4: Existence check across multiple conditions
You can stack conditions inside the expression itself:
The HDMI Cable matches both conditions, so any returns True after the third element. The generator only had to look at three items.
Pattern 5: Comparing two collections
any and all work over any iterable, including the result of zip:
There's a useful equivalence from logic that comes up when you write these checks. The statement "no items are out of stock" can be written two ways:
Both produce the same answer. Mathematically, this is De Morgan's law: "not (any x is bad)" equals "all x are not bad".
So which one should you write? Pick whichever reads better in context. A loose rule:
| Question you're answering | Reads better as |
|---|---|
| Is there even one bad item? | any(is_bad(x) for x in items) |
| Are all items good? | all(is_good(x) for x in items) |
| Are zero bad items present? | not any(is_bad(x) for x in items) |
| Is the cart entirely free of zeros? | all(stock > 0 for stock in stocks) |
When the natural English version contains "no" or "none", not any often sounds closer to the spoken form. When it's "every" or "all", all is the obvious choice. If you find yourself writing all(not ...), take a second look, not any(...) is usually clearer.
Cost: Both forms have the same short-circuit behavior. not any stops at the first match. all not stops at the first non-match. They do the same work in the same order, so pick on readability, not performance.
any and all are simple, but they let you replace whole loops with a single readable expression. Their combination of generator-expression syntax and short-circuit evaluation makes them efficient even on large inputs, and they pair naturally with the e-commerce checks you write all the time: stock validation, order status, review filters, price thresholds.
The two things to keep in your head: vacuous truth (all([]) == True) and "use a generator expression, not a list comprehension" so short-circuiting actually pays off. Once those are second nature, you'll find yourself reaching for these on almost every collection check.
10 quizzes