Python all() Function: Syntax, Usage, and Edge Cases
python all function: Learn how Python's all() function works, its syntax, behavior on empty iterables, and practical usage with generator expressions.
The Python all() function is a built-in that returns True if every element in an iterable evaluates to True, and False otherwise. It is often used for validation, checking conditions across collections, and simplifying boolean logic. Understanding python all function behavior is essential for writing concise and correct code, especially when dealing with empty iterables and generator expressions.
Syntax and Return Value
The syntax is straightforward:
all(iterable)
The function accepts any iterable—list, tuple, set, dictionary, string, or generator. It returns a boolean value:
Trueif all elements are truthy.Falseif at least one element is falsy.
Python's truthiness rules apply: 0, 0.0, None, False, empty strings, empty lists, empty dicts, and empty sets are falsy. Everything else is truthy.
print(all([1, 2, 3])) # True print(all([1, 0, 3])) # False print(all([True, True])) # True print(all([True, False])) # False
How all() Handles Different Iterables
all() works with any iterable, but the behavior can vary subtly depending on the type.
Lists and Tuples
Lists and tuples are the most common inputs. The function iterates over the elements and checks each one's truthiness.
values = [10, 20, 30] print(all(values)) # True values = [10, 0, 30] print(all(values)) # False
Strings
A string is iterable character by character. A non-empty string is truthy, but an empty string is falsy. This means all("hello") returns True because each character is a non-empty string. However, all("") returns True because there are no elements to check—the iterable is empty, and the function returns True for empty iterables (see below).
print(all("hello")) # True print(all("")) # True
Dictionaries
When you pass a dictionary, all() iterates over its keys, not values. This is a common source of confusion.
d = {"a": 1, "b": 2} print(all(d)) # True, because keys are non-empty strings d = {"a": 0, "b": 0} print(all(d)) # True, still checks keys, not values
To check values, use d.values() or d.items().
Empty Iterables
all() returns True for any empty iterable. This follows the mathematical convention that "for all" is vacuously true when there are no elements.
print(all([])) # True print(all(())) # True print(all({})) # True print(all(set())) # True
This behavior often surprises developers. If you need to ensure the iterable is non-empty, check its length separately.
Using all() with Generator Expressions
One of the most powerful patterns is combining all() with a generator expression. This avoids building a full list and short-circuits as soon as a falsy element is found.
numbers = [1, 2, 3, 4, 5] all_positive = all(n > 0 for n in numbers) print(all_positive) # True mixed = [1, -2, 3] all_positive = all(n > 0 for n in mixed) print(all_positive) # False
The generator expression yields values one at a time, and all() stops consuming as soon as it encounters a falsy result. This is memory-efficient for large datasets and can improve performance when the condition fails early.
Common Mistakes and Edge Cases
Using all() on a Single Boolean
all(True) raises a TypeError because a boolean is not iterable. The same applies to any non-iterable object.
# all(True) # TypeError: 'bool' object is not iterable
Assuming all() Checks Nested Structures
all() only checks the top-level elements. If an element is a list, its contents are not evaluated recursively.
nested = [[1, 2], []] print(all(nested)) # False, because the empty list is falsy
But all([1, [2, 3]]) returns True because both 1 and [2, 3] are truthy—the inner list's contents are irrelevant.
Confusing Truthiness with Equality
all() checks truthiness, not equality to True. For example, all([1, 2]) returns True even though 1 == True and 2 == True are both False. This is fine for most validation, but be explicit if you need exact boolean checks.
Performance Considerations
all() short-circuits: it stops evaluating as soon as it finds a falsy element. This is particularly beneficial when the iterable is large and the condition fails early.
Using a generator expression has two advantages:
- It avoids allocating a list of intermediate results.
- It allows
all()to stop generating values once the result is determined.
For example:
# List comprehension creates a full list first result1 = all([n % 2 == 0 for n in range(1000000)]) # Generator expression is lazy result2 = all(n % 2 == 0 for n in range(1000000))
The first version builds a list of one million booleans before all() runs. The second version evaluates each condition only until a False is found—in this case, at the first odd number, so it stops almost immediately.
Practical Examples: Validation and Condition Checking
A common use case is validating that all elements in a collection satisfy a condition, such as checking that all fields in a form are non-empty.
fields = {"name": "Alice", "email": "alice@example.com", "age": 30} all_present = all(fields.values()) print(all_present) # True
Another pattern is checking that all values in a dictionary are within a certain range.
scores = {"math": 85, "science": 92, "history": 78} all_passing = all(score >= 60 for score in scores.values()) print(all_passing) # True
all() also works well with custom objects that implement __bool__ or __len__. For example, checking that all elements in a list are non-empty strings:
words = ["hello", "world", ""] print(all(words)) # False
all() vs any()
any() is the complementary function: it returns True if at least one element is truthy. The two functions are often used together to express different logical conditions.
| Condition | Function | Example |
|---|---|---|
| All elements truthy | all() | all([1, 2, 3]) → True |
| At least one truthy | any() | any([0, 0, 1]) → True |
| No element truthy | not any() | not any([0, 0]) → True |
Both functions short-circuit and work with any iterable. Choosing between them depends on the logical requirement: use all() when every item must pass, any() when at least one must pass.
Advanced Usage: Combining all() with Custom Conditions
You can pass any callable that returns a boolean, but all() itself only accepts an iterable. The common pattern is to use a generator expression with a condition. For more complex logic, you can combine multiple conditions.
def is_valid_user(user): return all([ user.get("name"), user.get("email"), user.get("age", 0) >= 18 ]) users = [ {"name": "Alice", "email": "a@b.com", "age": 25}, {"name": "Bob", "email": "b@c.com", "age": 17} ] print(all(is_valid_user(u) for u in users)) # False
This approach keeps validation logic centralized and avoids scattered if statements. However, be cautious: all() with a list of conditions evaluates all conditions before returning, whereas a generator expression evaluates lazily. If you have side effects in conditions, the generator form is safer.
When Not to Use all()
all() is not always the best tool. If you need to know which element fails, a loop with an explicit break gives you more control. Also, if you are working with numpy arrays, the built-in all() behaves differently—numpy arrays have their own all() method that operates element-wise and can return an array. In such cases, use np.all() or the array's method.
import numpy as np arr = np.array([1, 2, 3]) print(arr.all()) # True, but this is numpy's method, not the built-in
For plain Python, all() is a clear and efficient way to express universal quantification. Understanding its behavior with empty iterables, generator expressions, and short-circuiting will help you avoid subtle bugs and write more idiomatic code.