Python's "all" and "any" keywords, and what happens when an empty iterable is passed
Tags: python, programming, tips, beginners
Published: 2020-12-27 10:04:49

Hello, world! 👋🏼

In this short post, let me take you through the happy li'l `any` and `all` keywords, along with a nice _gotcha_ later!

> Already aware of these keywords? Jump to the [gotcha](#gotcha) then.

# The `any` keyword

For the ones new to Python, both `any` and `all` accept an iterable.

> {% details A bit about iterables %} In case you are wondering what an `iterable` is, it's just an object that you can iterate over. Common examples include `list`, `tuple`, even `dict` and `str` (yes, you can iterate over them - try a `for` loop over them). There's more to `iterables`; some other day.. {% enddetails %}


`any` simply returns `True` if **any** of the elements in the iterable are truthy. Else, it returns `False`.

> {% details More about truthy %} `truthy` or `falsy` are simply those objects that evaluate to `True` or `False` when considered as boolean. To quickly check this, consider the below snippet: ```python
>>> bool(1)
True
>>> bool('a')
True
>>> bool(' ')
True
>>> bool(True)
True
>>> bool(0)
False
>>> bool('')
False
>>> bool(None)
False
>>> bool(False)
False
```{% enddetails %}



Let's see a few examples:
```python
>>> any([0, 1])
True
>>> any([1, 2])
True
>>> any([None, 1])
True
>>> any([0, 0])
False
>>> any([None, 0])
False
>>> any([False, None, 0])
False
```

# The `all` keyword

As you might have guessed, `all` returns `True` if **all** the elements in the iterable are truthy, else, `False`.

Let's see this with the same examples as above:
```python
>>> all([0, 1])    # this returned True for "any"
False
>>> all([1, 2])
True
>>> all([None, 1])
False
>>> all([0, 0])
False
>>> all([None, 0])
False
>>> all([False, None, 0])
False
```
Notice why only `[1, 2]` returned `True` for `all`..

---

# Gotcha

Now that we know what these keywords do, think about what will they return when you pass them an empty iterable?

Think for a while before going ahead..

Let's check:
```python
>>> any([])
False
>>> 
>>> all([])
True
>>> 
```
So, when we pass an empty list to `any`, it returns `False` (may be because an empty list is considered as falsy - quite intuitive). But behold! `all` returns `True` for an empty list!! Not very intuitive, eh?!

How could one ever know this? May be, by looking at the `help` on these functions:
```python
>>> help(any)
Help on built-in function any in module builtins:

any(iterable, /)
    Return True if bool(x) is True for any x in the iterable.
    
    If the iterable is empty, return False.
```

```python
>>> help(all)
Help on built-in function all in module builtins:

all(iterable, /)
    Return True if bool(x) is True for all values x in the iterable.
    
    If the iterable is empty, return True.
```
Note the last lines in both sections -
`any` - **`If the iterable is empty, return False.`**
`all` - **`If the iterable is empty, return True.`**

As a good practice, and towards becoming better at Python (or any language in general), always consider looking up at the documentation - it gives good insights about how things are implemented in the language.

_Happy coding.._