37

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 >

  • 1
    As pointed out, all states are simultaneously true and false for nothing, and a null set contains nothing. What really makes sense for your example is not `all(today_todo_tasks)`, but `any(map(lambda task: task.status != DONE, today_todo_tasks))`. – Silas Ray Aug 16 '12 at 13:33
  • possible duplicate of [Reason for "all" and "any" result on empty lists](http://stackoverflow.com/questions/3275058/reason-for-all-and-any-result-on-empty-lists) – Mark Mikofski Jan 01 '14 at 22:14
  • The C# Linq All extension method behaves the same way. – Larry Apr 13 '15 at 12:54
  • 1
    I think the duplicate as mentioned by @MarkMikofski has much clearer explanation to why question. – fatih_dur Apr 27 '16 at 05:28

7 Answers7

36

This is expressed as "For all X in S, X is true". If S is empty, there are no X. However, the truth statement remains True, because for all X, X was true... there just aren't any X!

Here is a explanation using logic.

Consider two sets A and B where A+B is the union of the two sets.

If any(A+B) = True -> any(A) or any(B) = True but we cannot assert either any(A)=True or any(B)=True.

If any(A+B) = False -> any(A) = False and any(B) = False.

If all(A+B) = True -> all(A)=True and all(B)=True

if all(A+B) = False -> all(A)=False or all(B)=False but we cannot assert either all(A)=False or all(B)=False.

Now instead of B, let's add the empty set Ø to A. We want to come up logic such that adding the empty set does not change the values of all() or any(), since A+Ø=A.

any(A+Ø) = any(A) or any(Ø)

any(Ø) must be False, so that if any(A) is True, any(A+Ø) is True, and if any(A) is False, any(A+Ø) is False.

all(A+Ø) = all(A) and all(Ø)

if all(A) is True, all(A+Ø) is True. Therefore, all(Ø) is True.

pepoluan
  • 6,132
  • 4
  • 46
  • 76
Interrobang
  • 16,984
  • 3
  • 55
  • 63
  • 21
    As this answer (correctly) implies, the all() function is intended to mimic the universal quantifier in mathematics, which is defined to be true when applied to the empty set. See http://en.wikipedia.org/wiki/Vacuous_truth for a discussion of why this is the case, and why it feels wrong to many (including the OP). – happydave Aug 16 '12 at 02:20
  • 1
    vacuous truth leads to bugs; `if all(nuclear_sub.has_been_destroyed for nuclear_sub in fleet): launch_doomsday_device() ` Now what happens on the day we decommission the last sub?? – EoghanM Sep 20 '18 at 01:45
10

all() (documented to "Return True if all elements of the iterable are true (or if the iterable is empty).") is equivalent to the following:

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

Since there are no elements, it will skip the loop and return True.

Cat
  • 66,919
  • 24
  • 133
  • 141
  • 5
    This is just circular logic that begs the question. 'It was defined this way because this is the way it was defined' is not really an answer... – Silas Ray Aug 16 '12 at 02:12
  • I saw that on the docs.. but it does not answer the question. Why not check if the **iterable** is False and return it? – Bruno Rocha - rochacbruno Aug 16 '12 at 02:13
  • 1
    @sr2222 It shows the logic behind how `all()` operates. By showing that the method returns `True` unless there is a `False` element in it, we can understand why it returns `True` for an empty list. – Cat Aug 16 '12 at 02:15
  • @rochacbruno Why would you check if it was `False` first? A list with all `True` elements can be empty; a set of 0 elements is still a set that contains no `False` elements. – Cat Aug 16 '12 at 02:16
  • 2
    The question is not how does it operate, but why was it made to operate that way. @Interrobang actually provides an explanation. It is as if rochacbruno asked, "why does the Earth rotate around the sun," you answered, "because an orbit is defined as a body moving around another body," and Interrobang answered, "gravity." – Silas Ray Aug 16 '12 at 02:21
2

This comes from the mathematical logic.

"everything is true of the elements of the empty set" (http://en.wikipedia.org/wiki/Empty_set)

See also http://en.wikipedia.org/wiki/Vacuous_truth

Yevgen Yampolskiy
  • 7,022
  • 3
  • 26
  • 23
2

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

Mo...
  • 1,812
  • 2
  • 17
  • 22
1

Because all elements are True. When there are no elements, you can say that 'all elements are ... anything'

Piotr Findeisen
  • 19,480
  • 2
  • 52
  • 82
0

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

nehem
  • 12,775
  • 6
  • 58
  • 84
0

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]
JayS
  • 2,057
  • 24
  • 16