Python's all(): Check Your Iterables for Truthiness

Python's all(): Check Your Iterables for Truthiness

by Leodanis Pozo Ramos Feb 09, 2022 basics best-practices python

When programming, you’ll often need to check if all the items in an iterable are truthy. Coding this functionality repeatedly can be annoying and inefficient. Luckily, Python provides the built-in all() function to solve this problem. This function takes an iterable and checks all its items for truth value, which is handy for finding out if those items have a given property or meet a particular condition.

Python’s all() is a powerful tool that can help you write clean, readable, and efficient code in Python.

In this tutorial, you’ll learn how to:

  • Check if all the items in an iterable are truthy by using all()
  • Use all() with different iterable types
  • Combine all() with comprehensions and generator expressions
  • Distinguish between all() and the Boolean and operator

To complement this knowledge, you’ll code several examples that showcase exciting use cases of all() and highlight the many ways to use this function in Python programming.

To understand the topics in this tutorial, you should have basic knowledge of several Python concepts, such as iterable data structures, Boolean types, expressions, operators, list comprehensions, and generator expressions.

Evaluating the Truth Value of Items in Iterables

A pretty common problem in programming is determining if all the items in a list or array are truthy or not. For example, you may have the following list of conditions:

  • 5 > 2
  • 1 == 1
  • 42 < 50

To figure out if these conditions are true, you need to iterate over them and test every condition for truthiness. In this example, you have that 5 > 2 is true, 1 == 1 is true, and 42 < 50 is also true. As a result, you can say that all these conditions are true. If at least one of the conditions were false, then you would say that not all the conditions are true.

Note that as soon as you find a falsy condition, you can stop evaluating conditions because, in that case, you already know the final result: not all are true.

To solve this problem by writing custom Python code, you can use a for loop to iterate over each condition and evaluate it for truthiness. Your loop will iterate until it finds a falsy item, at which point it’ll stop because you already have a result:

>>>
>>> def all_true(iterable):
...     for item in iterable:
...         if not item:
...             return False
...     return True
...

This function takes an iterable as an argument. The loop iterates over the input argument while the conditional if statement checks if any item is falsy using the not operator. If an item is falsy, then the function immediately returns False, signaling that not all the items are true. Otherwise, it returns True.

This function is quite generic. It takes an iterable, which means you can pass in a list, tuple, string, dictionary, or any other iterable data structure. To check if the current item is true or false, all_true() uses the not operator to invert the truth value of its operand. In other words, it returns True if its operand evaluates to false and vice versa.

Python’s Boolean operators can evaluate the truth value of expressions and objects, which guarantees that your function can take iterables containing objects, expressions, or both. For example, if you pass in an iterable of Boolean expressions, then not just evaluates the expression and negates the result.

Here’s all_true() in action:

>>>
>>> bool_exps = [
...     5 > 2,
...     1 == 1,
...     42 < 50,
... ]
>>> all_true(bool_exps)
True

Because all the expressions in the input iterable are true, not negates the result, and the if code block never runs. In that case, all_true() returns True.

Something similar happens when the input iterable holds Python objects and non-Boolean expressions:

>>>
>>> objects = ["Hello!", 42, {}]
>>> all_true(objects)
False

>>> general_expressions = [
...     5 ** 2,
...     42 - 3,
...     int("42")
... ]
>>> all_true(general_expressions)
True

>>> empty = []
>>> all_true(empty)
True

In the first example, the input list contains regular Python objects, including a string, a number, and a dictionary. In this case, all_true() returns False because the dictionary is empty and evaluates to false in Python.

To perform truth value testing on objects, Python has an internal set of rules for objects that evaluate as false:

Any other object evaluates as true when you test it for truthiness in Python.

In the second example, the input list contains general Python expressions, such as math expressions and function calls. In this case, Python first evaluates the expression to get its resulting value, and then it checks that value for truthiness.

The third example highlights an important detail of all_true(). When the input iterable is empty, then the for loop doesn’t run, and the function returns True immediately. This behavior can seem weird at first glance. However, the logic behind it is that if there are no items in the input iterable, then there’s no way to say if any items are falsy. So, the function returns True with empty iterables.

Even though coding all_true() is pretty straightforward in Python, it can be annoying to write this custom function every time you need its functionality. Determining if all the items in an iterable are true is such a common task in programming that Python provides the built-in all() function for the job.

Getting Started With Python’s all()

If you check out the documentation for Python’s all(), then you’ll note that the function is equivalent to the function you coded in the previous section. However, like all built-in functions, all() is a C function and is optimized for performance.

Guido van Rossum proposed the all() and any() functions in an effort to remove functools.reduce() and other functional tools, such as filter() and map(), from Python. However, the Python community wasn’t happy with removing these tools. Even so, all() and any() were added as built-in functions in Python 2.5, with implementations by Raymond Hettinger.

It’s possible to say that Python’s all() performs a reduction or folding operation because it reduces an iterable of items to a single object. However, it’s not a higher-order function because it doesn’t take other functions as arguments to perform its computation. So, you can consider all() a regular predicate or Boolean-valued function.

You can use all() to check if all of the items in an input iterable are true. Because it’s a built-in function, you don’t need to import it. Here’s how it works:

>>>
>>> bool_exps = [
...     5 > 2,
...     1 == 1,
...     42 < 50,
... ]
>>> all(bool_exps)
True

>>> objects = ["Hello!", 42, {}]
>>> all(objects)
False

>>> general_exps = [
...     5 ** 2,
...     42 - 3,
...     int("42")
... ]
>>> all(general_exps)
True

>>> empty = []
>>> all(empty)
True

These examples show that all() works the same as your custom function, all_true(). Internally, all() loops over the items in the input iterable, checking their truth values. If it finds a falsy item, then it returns False. Otherwise, it returns True.

If you call all() with an empty iterable, as you did in the final example above, then you get True because there is no falsy item in an empty iterable. Note that all() evaluates the items in the input iterable rather than the iterable itself. See Why Does all() Return True if the Iterable is Empty? for a more philosophical discussion about this.

To summarize the behavior of all(), here’s its table of truth:

Condition Result
All items evaluate as true. True
All items evaluate as false. False
One or more items evaluate as false. False
The input iterable is empty. True

You can run the following calls to all() to confirm the information in this table:

>>>
>>> all([True, True, True])
True

>>> all([False, False, False])
False

>>> all([False, True, True])
False

>>> all([])
True

These examples show that all() returns True when all the items in the input iterable are true or when the iterable is empty. Otherwise, the function returns False.

Just like your all_true() function, all() also implements what’s known as short-circuit evaluation. This kind of evaluation means that all() will return as soon as it determines the operation’s final result.

The short-circuiting happens when the function finds a falsy item in the iterable. In that case, there’s no need to evaluate the rest of the items because the function already knows the final result. Note that this type of implementation means that you can get different behaviors when you test conditions with side effects. Consider the following example:

>>>
>>> def is_true(value):
...     print("Side effect!")
...     return bool(value)
...

>>> values = [0, 1]

>>> conditions = (is_true(n) for n in values)
>>> all(conditions)
Side effect!
False

>>> conditions = (is_true(n) for n in reversed(values))
>>> all(conditions)
Side effect!
Side effect!
False

The is_true() function takes an object as an argument and returns its truth value. During the function’s execution, a side effect takes place: the function prints something to the screen.

The first instance of conditions holds a generator expression that yields truth values after lazily evaluating each item from an input iterable, which is values in the example. This time, all() only evaluates the function one time because is_true(0) returns False. The side effect runs only once.

Now check out the second instance of conditions. If you reverse the input iterable, then all() evaluates both items because the call to is_true() with 1 as an argument returns True. The side effect runs twice.

This behavior can be a source of subtle issues, so you should avoid evaluating conditions with side effects in your code.

Finally, when it come to using the all() function, you can say that it has at least two generic use cases. You can use all() to check if all items in an iterable:

  1. Evaluate to true
  2. Have a given property or meet a certain condition

In the following section, you’ll learn how to use all() with different iterable types in Python. After that, you’ll learn how to use all() with list comprehensions and generator expressions to solve the second use case listed above.

Using all() With Different Iterable Types

The built-in all() function embraces Python’s duck typing style and accepts different argument types as long as they’re iterable. You can use all() with lists, tuples, strings, dictionaries, sets, and the like.

In all cases, all() does its work as expected, returning True if all the items are truthy and False otherwise. In this section, you’ll code examples using all() with different iterable types.

Sequences

Up to this point, you’ve learned how all() works with Python lists. In this section, you’ll learn that there’s no real difference between lists and other sequence data types, such as tuples, and range objects. All the function needs is for the input object to be iterable.

Here are a few examples of using all() with tuples and range objects:

>>>
>>> # With tuples
>>> all((1, 2, 3))
True
>>> all((0, 1, 2, 3))
False
>>> all(())
True
>>> all(tuple())
True

>>> # With range objects
>>> all(range(10))
False
>>> all(range(1, 11))
True
>>> all(range(0))
True

As usual, if all the items in the input iterable are truthy, then you get True. Otherwise, you get False. Empty tuples and ranges produce a True result. In the last example, calling range() with 0 as an argument returns an empty range object, so all() gives you True as a result.

You can also pass tuples containing expressions, Boolean expressions, or Python objects of any type to all(). Go ahead and give it a try!

Dictionaries

Dictionaries are collections of key-value pairs. If you iterate through a dictionary directly, then you’ll loop over its keys automatically. In addition, you can use convenience methods to explicitly iterate dictionaries’ keys, values, and items.

If you pass a dictionary directly to all(), then the function will check the dictionary’s keys automatically:

>>>
>>> all({"gold": 1, "silver": 2, "bronze": 3})
True

>>> all({0: "zero", 1: "one", 2: "two"})
False

Because all the keys in the first dictionary are truthy, you get True as a result. In the second dictionary, the first key is 0, which evaluates to false. In this case, you get False back from all().

If you want to get the same result as in the examples above, but with more readable and explicit code, then you can use the .keys() method, which returns all the keys from the underlying dictionary:

>>>
>>> medals = {"gold": 1, "silver": 2, "bronze": 3}
>>> all(medals.keys())
True

>>> numbers = {0: "zero", 1: "one", 2: "two"}
>>> all(numbers.keys())
False

With .keys(), you make it explicit that your code calls all() to determine if all the current keys in the input dictionary are truthy.

Another common requirement is that you need to check if all the values in a given dictionary evaluate as true. In that case, you can use .values():

>>>
>>> monday_inventory = {"book": 2, "pencil": 5, "eraser": 1}
>>> all(monday_inventory.values())
True

>>> tuesday_inventory = {"book": 2, "pencil": 3, "eraser": 0}
>>> all(tuesday_inventory.values())
False

In these examples, you first check if there’s at least one item in your current inventory of school supplies. On Monday, all your items have at least one unit, so all() returns True. However, on Tuesday, the call to all() returns False because you’ve run out of units in at least one of your supplies, eraser in this case.

Using all() With Comprehensions and Generator Expressions

As you learned earlier, the second use case of Python’s all() is to check if all the items in an iterable have a given property or meet a certain condition. To do this kind of check, you can use all() with a list comprehension or a generator expression as an argument, depending on your needs.

The synergy you get by combining all() with list comprehensions and generator expressions unchains the full power of this function and makes it quite valuable in your day-to-day coding.

One way to leverage this superpower of all() is by using a predicate function that tests for the desired property. This predicate function will be the expression in the list comprehension that you’ll pass as an argument to all(). Here’s the required syntax:

all([predicate(item) for item in iterable])

This list comprehension uses predicate() to test each item in iterable for a given property. Then the call to all() reduces the resulting list to a single True or False value, which tells you if all the items have the property that predicate() defines and tests.

For example, the following code checks if all the values in a sequence are prime numbers:

>>>
>>> import math

>>> def is_prime(n):
...     if n <= 1:
...         return False
...     for i in range(2, math.isqrt(n) + 1):
...         if n % i == 0:
...             return False
...     return True
...

>>> numbers = [2, 3, 5, 7, 11]
>>> all([is_prime(x) for x in numbers])
True

>>> numbers = [2, 4, 6, 8, 10]
>>> all([is_prime(x) for x in numbers])
False

In this example, you combine all() with a list comprehension. The comprehension uses the is_prime() predicate function to test each value in numbers for primality. The resulting list will contain Boolean values (True or False) for the result of every check. Then all() gets this list as an argument and processes it to determine if all the numbers are prime or not.

The second use case of this magical combination, all() plus a list comprehension, is to check if all the items in an iterable meet a given condition. Here’s the required syntax:

all([condition for item in iterable])

This call to all() uses a list comprehension to check if all the items in iterable satisfy the required condition, which is generally defined in terms of an individual item. Following this idea, here are a couple of examples that check if all the numbers in a list are greater than 0:

>>>
>>> numbers = [1, 2, 3]
>>> all([number > 0 for number in numbers])
True

>>> numbers = [-2, -1, 0, 1, 2]
>>> all([number > 0 for number in numbers])
False

In the first example, all() returns True because all the numbers in the input list meet the condition of being greater than 0. In the second example, the result is False because the input iterable includes 0 and negative numbers.

As you already know, all() returns True with an empty iterable as an argument. This behavior may seem weird and can lead to wrong conclusions:

>>>
>>> numbers = []

>>> all([number < 0 for number in numbers])
True

>>> all([number == 0 for number in numbers])
True

>>> all([number > 0 for number in numbers])
True

This code shows that all the values in numbers are less than 0, but they’re also equal to and greater than 0, which is impossible. The root cause of this illogical result is that all these calls to all() evaluate empty iterables, which makes all() return True.

To work around this issue, you can use the built-in len() function to get the number of items in the input iterable. If len() returns 0, then you can skip calling all() to process the empty input iterable. This strategy will make your code less error-prone.

All the examples that you’ve coded in this section use a list comprehension as an argument to all(). A list comprehension creates a complete list in memory, which can be a wasteful operation. This behavior holds especially true if you don’t need the resulting list in your code anymore, which is the typical case with all().

In this situation, it’s always more efficient to use all() with a generator expression instead, especially if you’re working with a long input list. Instead of building an entire new list in memory, a generator expression will generate and yield items on demand, making your code more efficient.

The syntax to build a generator expression is almost the same as what you used for a list comprehension:

# With a predicate
all(predicate(item) for item in iterable)

# With a condition
all(condition for item in iterable)

The only difference is that a generator expression uses parentheses (()) instead of square brackets ([]). Because a function call will already require parentheses, you just need to remove the square brackets.

Unlike list comprehensions, generator expressions yield items on demand, making them quite efficient in terms of memory usage. Additionally, you won’t create a new list just to throw it away after all() returns.

Comparing all() With the and Boolean Operator

You can roughly think of all() as a series of items connected through the Boolean and operator. For example, the function call all([item1, item2, ..., itemN]) is semantically equivalent to the expression item1 and item2 ... and itemN. However, there are some tiny differences between them.

In this section, you’ll learn about those differences. The first one has to do with syntax, and the second is about the return value. Additionally, you’ll learn that both all() and the and operator implement short-circuit evaluation.

Understanding Syntax Differences

A call to all() uses the same syntax as any function call in Python. You need to call the function with a pair of parentheses. In the specific case of all(), you have to pass in an iterable of values as an argument:

>>>
>>> all([True, False])
False

The items in the input iterable can be general expressions, Boolean expressions, or Python objects of any type. Additionally, the number of items in the input iterable depends only on the amount of memory available on your system.

On the other hand, the and operator is a binary operator that connects two operands in an expression:

>>>
>>> True and False
False

The logical and operator takes a left and a right operand to build a compound expression. Just like with all(), the operands in an and expression can be general expressions, Boolean expressions, or Python objects. Finally, you can use multiple and operators to connect any number of operands.

Returning Boolean Values vs Operands

The second and even more important difference between all() and the and operator is their respective return values. While all() always returns True or False, the and operator always returns one of its operands. It only returns True or False if the returned operand explicitly evaluates to either value:

>>>
>>> all(["Hello!", 42, {}])
False
>>> "Hello!" and 42 and {}
{}

>>> all([1, 2, 3])
True
>>> 1 and 2 and 3
3

>>> all([0, 1, 2, 3])
False
>>> 0 and 1 and 2 and 3
0

>>> all([5 > 2, 1 == 1])
True
>>> 5 > 2 and 1 == 1
True

These examples show how all() always returns True or False, which is consistent with the status of a predicate function. On the other hand, and returns the last evaluated operand. If it happens to be the last operand in an expression, then all the previous ones must have been truthy. Otherwise, and will return the first falsy operand, indicating where the evaluation stopped.

Notice that in the final example, the and operator returns True because the implied operands are comparison expressions, which always return True or False explicitly.

This is an important difference between the all() function and the and operator. So, you should take it into account to prevent subtle bugs in your code. However, in Boolean contexts, such as if statements and while loops, this difference isn’t relevant at all.

Short-Circuiting the Evaluation

As you already learned, all() short-circuits the evaluation of the items in the input iterable when it determines the final result. The and operator also implements short-circuit evaluation.

The advantage of this feature is that it makes the operation efficient by skipping the remaining checks as soon as a falsy item appears.

To try out short-circuit evaluation, you can use a generator function, as in the following example:

>>>
>>> def generate_items(iterable):
...     for i, item in enumerate(iterable):
...         print(f"Checking item: {i}")
...         yield item
...

The loop inside generate_items() iterates over the items in iterable, using the built-in enumerate() function to get the index of every checked item. Then the loop prints a message identifying the checked item and yields the item at hand.

With generate_items() in place, you can run the following code to test all() for short-circuit evaluation:

>>>
>>> # Check both items to get the result
>>> items = generate_items([True, True])
>>> all(items)
Checking item: 0
Checking item: 1
True

>>> # Check the first item to get the result
>>> items = generate_items([False, True])
>>> all(items)
Checking item: 0
False

>>> # Still have a remaining item
>>> next(items)
Checking item: 1
True

The first call to all() shows how the function checks both items to determine the final result. The second call confirms that all() only checks the first item. Since this item is falsy, the function returns immediately without checking the second item. That’s why the generator still produces a second item when you call next().

Now you can run a similar test using the and operator:

>>>
>>> # Check both items to get the result
>>> items = generate_items([True, True])
>>> next(items) and next(items)
Checking item: 0
Checking item: 1
True

>>> # Check the first item to get the result
>>> items = generate_items([False, True])
>>> next(items) and next(items)
Checking item: 0
False

>>> # Still have a remaining item
>>> next(items)
Checking item: 1
True

The first and expression evaluates both operands to get the final result. The second and expression only evaluates the first operand to determine the result. The call to next() with items as an argument shows that the generator function still yields a remaining item.

Putting all() Into Action: Practical Examples

So far, you’ve learned the basics of Python’s all(). You’ve learned to use it with sequences, dictionaries, list comprehensions, and generator expressions. Additionally, you’ve learned about the differences and similarities between this built-in function and the logical and operator.

In this section, you’ll code a series of practical examples that will help you assess how useful all() can be while you’re programming with Python. So, stay tuned and enjoy your coding!

Improving the Readability of Long Compound Conditions

One interesting feature of all() is how this function can improve the code’s readability when you’re working with long compound Boolean expressions based on the and operator.

For example, say you need to validate the user’s input in a piece of code. For the input to be valid, it should be an integer number between 0 and 100 that’s also an even number. To check all these conditions, you can use the following if statement:

>>>
>>> x = 42

>>> if isinstance(x, int) and 0 <= x <= 100 and x % 2 == 0:
...     print("Valid input")
... else:
...     print("Invalid input")
...
Valid input

The if condition consists of a call to isinstance() that checks if the input is an integer number, a chained comparison expression that checks if the number is between 0 and 100, and an expression that checks if the input value is an even number.

Even though this code works, the condition is quite long, which makes it difficult to parse and understand. Additionally, if you need to add more validation checks in future updates, then the condition will get longer and more complicated. It’d also require some code formatting.

To improve the readability of this conditional, you can use all(), like in the following code:

>>>
>>> x = 42

>>> validation_conditions = (
...     isinstance(x, int),
...     0 <= x <= 100,
...     x % 2 == 0,
... )

>>> if all(validation_conditions):
...     print("Valid input")
... else:
...     print("Invalid input")
...
Valid input

In this example, all the validation conditions live in a tuple with a descriptive name. Using this technique has an additional advantage: if you ever need to add a new validation condition, then you just have to add a new line to your validation_conditions tuple. Note that now your if statement holds a pretty readable, explicit, and concise expression based on all().

In real life, a validation strategy typically would allow you to reuse your validation code. For example, instead of specifying plain conditions that evaluate only once, you can code reusable validation functions:

>>>
>>> def is_integer(x):
...     return isinstance(x, int)
...

>>> def is_between(a=0, b=100):
...     return lambda x: a <= x <= b
...

>>> def is_even(x):
...     return x % 2 == 0
...

>>> validation_conditions = (
...     is_integer,
...     is_between(0, 100),
...     is_even,
... )

>>> for x in (4.2, -42, 142, 43, 42):
...     print(f"Is {x} valid?", end=" ")
...     print(all(condition(x) for condition in validation_conditions))
...
Is 4.2 valid? False
Is -42 valid? False
Is 142 valid? False
Is 43 valid? False
Is 42 valid? True

In this example, you have three functions that check your three original conditions in a reusable way. Then you redefine your tuple of validation conditions using the functions you just coded. The final for loop shows how you can reuse these functions to validate several input objects using all().

Validating Iterables of Numeric Values

Another interesting use case of all() is to check if all the numeric values in an iterable are in a given interval. Here are a few examples of how to do this for different conditions and with the help of a generator expression:

>>>
>>> numbers = [10, 5, 6, 4, 7, 8, 20]

>>> # From 0 to 20 (Both included)
>>> all(0 <= x <= 20 for x in numbers)
True

>>> # From 0 to 20 (Both excluded)
>>> all(0 < x < 20 for x in numbers)
False

>>> # From 0 to 20 (integers only)
>>> all(x in range(21) for x in numbers)
True

>>> # All greater than 0
>>> all(x > 0 for x in numbers)
True

These examples show how you can build generator expressions to check if all the values in an iterable of numbers are in a given interval.

The technique in the examples above allows a lot of flexibility. You can tweak the condition and use all() to run all kinds of checks on the target iterable.

Validating Strings and Iterables of Strings

The built-in str type implements several predicate string methods that can be useful when you need to validate iterables of strings and individual characters in a given string.

For example, with those methods, you can check if a string is a valid decimal number, if it’s an alphanumeric character, or if it’s a valid ASCII character.

Here are a few examples of using string methods in your code:

>>>
>>> numbers = ["1", "2", "3.0"]

>>> all(number.isdecimal() for number in numbers)
True

>>> chars = "abcxyz123"

>>> all(char.isalnum() for char in chars)
True

>>> all(char.isalpha() for char in chars)
False

>>> all(char.isascii() for char in chars)
True

>>> all(char.islower() for char in chars)
False

>>> all(char.isnumeric() for char in chars)
False

>>> all(char.isprintable() for char in chars)
True

Each of these .is*() methods checks a specific property on the underlying string. You can take advantage of these and several other string methods to validate items in an iterable of strings as well as individual characters in a given string.

Removing Rows With Empty Fields From Tabular Data

When you’re working with tabular data, you may face the issue of having empty fields. Cleaning the rows containing empty fields may be a requirement for you. If that’s the case, then you can use all() and filter() to extract the rows that have data in all their fields.

The built-in filter() function takes a function object and an iterable as arguments. Typically, you’ll use a predicate function as the first argument to filter(). A call to filter() applies the predicate to every item in the iterable and returns an iterator with the items that make the predicate return True.

You can use all() as the predicate in a filter() call. This way, you can process lists of lists, which can be useful when you’re working with tabular data.

For a concrete example, say you have a CSV file with data about your company’s employees:

name,job,email
"Linda","Technical Lead",""
"Joe","Senior Web Developer","joe@example.com"
"Lara","Project Manager","lara@example.com"
"David","","david@example.com"
"Jane","Senior Python Developer","jane@example.com"

With a quick look at this file, you’ll note that some rows hold empty fields. For example, the first row doesn’t have an email, and the fourth row doesn’t provide a position or role. You need to clean up the data by removing rows containing empty fields.

Here’s how you can satisfy that requirement by using all() as the predicate in a filter() call:

>>>
>>> import csv
>>> from pprint import pprint

>>> with open("employees.csv", "r") as csv_file:
...     raw_data = list(csv.reader(csv_file))
...

>>> # Before cleaning
>>> pprint(raw_data)
[['name', 'job', 'email'],
 ['Linda', 'Technical Lead', ''],
 ['Joe', 'Senior Web Developer', 'joe@example.com'],
 ['Lara', 'Project Manager', 'lara@example.com'],
 ['David', '', 'david@example.com'],
 ['Jane', 'Senior Python Developer', 'jane@example.com']]

>>> clean_data = list(filter(all, raw_data))

>>> # After cleaning
>>> pprint(clean_data)
[['name', 'job', 'email'],
 ['Joe', 'Senior Web Developer', 'joe@example.com'],
 ['Lara', 'Project Manager', 'lara@example.com'],
 ['Jane', 'Senior Python Developer', 'jane@example.com']]

In this example, you first load the content of the target CSV file into raw_data by using the csv module from the Python standard library. The call to the pprint() function shows that the data contains rows with empty fields. Then you clean up the data with filter() and all().

How do the filter() and all() functions work together to execute the task? Well, if all() finds an empty field in a row, then it returns False. With that result, filter() won’t include that row in the final data. To make sure that this technique works, you can call pprint() with the clean data as an argument.

Comparing Custom Data Structures

As another example of how to use all(), say you need to create a custom list-like class that allows you to check if all its values are greater than a specific value.

To create this custom class, you can subclass UserList from the collections module and then override the special method called .__gt__(). Overriding this method allows you to overload the greater than (>) operator, providing a custom behavior for it:

>>>
>>> from collections import UserList

>>> class ComparableList(UserList):
...     def __gt__(self, threshold):
...         return all(x > threshold for x in self)
...

>>> numbers = ComparableList([1, 2, 3])

>>> numbers > 0
True

>>> numbers > 5
False

In .__gt__(), you use all() to check if all the numbers in the current list are greater than a specific threshold value that should come from the user.

The comparison expressions at the end of this code snippet show how to use your custom list and how it behaves with the greater than (>) operator. In the first expression, all the values in the list are greater than 0, so the result is True. In the second expression, all the numbers are less than 5, which results in a False outcome.

Partially Emulating Python’s zip() Function

Python’s built-in zip() function is useful for looping over multiple iterables in parallel. This function takes a given number of iterables (N) as arguments and aggregates elements from each of them into N-items tuples. In this example, you’ll learn how to use all() to partially simulate this functionality.

To better understand the challenge, check out the basics of what zip() does:

>>>
>>> numbers = zip(["one", "two"], [1, 2])

>>> list(numbers)
[('one', 1), ('two', 2)]

In this example, you pass two lists as arguments to zip(). The function returns an iterator that yields tuples of two items each, which you can confirm by calling list() with the resulting iterator as an argument.

Here’s a function that simulates this functionality:

>>>
>>> def emulated_zip(*iterables):
...     lists = [list(iterable) for iterable in iterables]
...     while all(lists):
...         yield tuple(current_list.pop(0) for current_list in lists)
...

>>> numbers = emulated_zip(["one", "two"], [1, 2])

>>> list(numbers)
[('one', 1), ('two', 2)]

Your emulated_zip() function can take a variable number of arguments consisting of iterable objects. The first line inside the function uses a list comprehension to convert each input iterable into a Python list so that you can later use its .pop() method. The loop condition relies on all() to check if all the input lists contain at least one item.

In every iteration, the yield statement returns a tuple containing one item from each input list. The call to .pop() with 0 as an argument retrieves and removes the first item from each list.

Once the loop iterates enough times that .pop() removes all the items from either list, the condition becomes false, and the function terminates. The loop ends when the shortest iterable gets exhausted, truncating longer iterables. This behavior is consistent with the default behavior of zip().

Note that your function only partially emulates the built-in zip() function because yours doesn’t take the strict argument. This argument was added in Python 3.10 as a safe way to handle iterables of unequal length.

Conclusion

Now you know how to check if all the items in an existing iterable are truthy by using Python’s built-in all() function. You also know how to use this function to find out if the items in an iterable meet a given condition or have a specific property.

With this knowledge, you’re now able to write more readable and efficient Python code.

In this tutorial, you learned:

  • How to use Python’s all() to check if all the items in an iterable are truthy
  • How all() works with different iterable types
  • How to combine all() with comprehensions and generator expressions
  • What makes all() different from and similar to the and operator

Additionally, you coded several practical examples that helped you understand how powerful all() can be and what some of its most common use cases in Python programming are.

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

About Leodanis Pozo Ramos

Leodanis Pozo Ramos Leodanis Pozo Ramos

Leodanis is an industrial engineer who loves Python and software development. He's a self-taught Python developer with 6+ years of experience. He's an avid technical writer with a growing number of articles published on Real Python and other sites.

» More about Leodanis

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

Master Real-World Python Skills With Unlimited Access to Real Python

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

Master Real-World Python Skills
With Unlimited Access to Real Python

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:
Tweet Share Share Email

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal.


Looking for a real-time conversation? Visit the Real Python Community Chat or join the next “Office Hours” Live Q&A Session. Happy Pythoning!

Keep Learning

Related Tutorial Categories: basics best-practices python