Reputation: 8168
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 >
Upvotes: 37
Views: 11042
Reputation: 17434
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.
Upvotes: 36
Reputation: 1971
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 alsoFalse
This contradicts. As a result, the first assumption is wrong and
all([])
is True
Upvotes: 2
Reputation: 2303
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]
Upvotes: 0
Reputation: 13662
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
Upvotes: 0
Reputation: 7198
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
Upvotes: 2
Reputation: 20770
Because all elements are True. When there are no elements, you can say that 'all elements are ... anything'
Upvotes: 1
Reputation: 67522
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
.
Upvotes: 11