Why Python built in "all" function returns True for empty iterables?

Viewed 10379

I know it has a good reason, but I want to know what reason?

>>> print all([])
True

If all() is intended to check if every item on iterable evaluates to "True", and we know empty lists are evaluated to False

>>> bool([])
False

So why the all() returns True for empty lists?

< edit >

I already read the docs, and I know the implementation

 def all(iterable):
    for element in iterable:
        if not element:
            return False
    return True

But the question is why not?

def all(iterable):
    if not iterable:
        return False
    for element in iterable:
        if not element:
            return False
    return True

There is a logic on this? if you have a list of done-tasks

today_todo_status = [task.status for task in my_todo if task.date == today]
can_i_go_home = all(today_todo_status)

Ok, on the above hypothetical example it really makes sense, if I have no tasks, so I can go home.

But there are other cases and I dont think all() was made for todo lists.. LOL

< /edit >

7 Answers

Suppose all([]) is False.

Then, for all non empty list A, all(A + []) should be also False as

all(A + []) = all(A) and all([])
            = all(A) and False
            = False

Since A + [] = A, we know

all(A + []) = all(A) for any non empty list A

But, all(A) could be True (e.g., A = [True])

Hence,

for all non empty list A, all(A + []) should be also False

This contradicts. As a result, the first assumption is wrong and

all([]) is True

ELI5 version.

Take a list of numbers

L = [1,2,3,4,6]

all([isintance(l, int) for l in L])

all is defined in such a way that, the only way to make it False is by supplying at least one non-integer.

Similarly any is defined in a way that, to make it True all you need is at-least one positive integer.

Since all() is the complement of any() one must be True and other must be False

When testing for a condition, we want the first element to always be added to the list. For example, if we only want to add numbers to a list if they are less than the smallest number or greater than the largest number we can do this:

def addToList(less,num):
    if less:
        if any( num >= savedNum for savedNum in numbers):
            print('{} is not less'.format(num))
            return
    elif any( num <= savedNum for savedNum in numbers):
        print('{} is not greater'.format(num))
        return

    numbers.append(num)


numbers = []
doLess = True
doMore = False
addToList(doLess,5) #numbers is empty, but will be added
addToList(doLess,2)
addToList(doLess,7)
addToList(doMore,15)
addToList(doMore,9)
print(numbers)

Output:

7 is not less [5, 2]
9 is not greater [5, 2, 15]
[5, 2, 15]
Related