Reputation: 1407
I am looking at the behavior of the all
function in Python and it's behavior struck me as not very intuitive when it comes to empty lists. I would assume there is a good rationale and deliberation that went into the decision for such a choice and probably there is a solid mathematical explanation in some form. I am curious to know what is the foundation for such behaviors where comparisons with an empty set results in true
results.
I am referring to the following python code
all(a==2 for a in my_list)
I expect the above code to return True if all the elements in my_list are 2. but when I make my_list empty and run it as
my_list = []
all(a==2 for a in my_list)
it returns True as well. I am confused with this behaviour. Is it not supposed to return False as there is no element in my_list with value 2?
Upvotes: 26
Views: 11629
Reputation: 17131
It's true because for every element in the list, all 0 of them, they all are equal to 2.
You can think of all being implemented as:
def all(my_list, condition):
for a in my_list:
if not condition(a):
return False
return True
Whereas any is:
def any(my_list, condition):
for a in my_list:
if condition(a):
return True
return False
That is to say, all
is innocent until proven guilty, and any
is guilty until proven innocent.
Upvotes: 48
Reputation: 1524
"all" applied to an empty list is "vacuously true", as is easily confirmed:
>>> all([])
True
Similarly, "if 0 = 1 then the moon is square" is true. More generally, "all P are Q" -- if there are no P's then the statement is considered true, as it can be captured formally as "For all x, if x is P then x is Q". Ultimately, these are true because the conditional logical operator (if-then) evaluates to True whenever the antecedent (the first clause) is False: "if False then True" evaluates to True. Recall that "if A then B" is equivalent to "(not A) or B".
Added 1-2022
In the case of all
and Python lists, the boolean value of all(my_list)
is the value of
"for all items `x` in `my_list`, the value of `x` is truthy".
When my_list
is empty, that value is True. Again, "for all" and all
make no existence claim.
In Python pseudocode, all
works roughly like this:
val = True
for x in my_list:
if not x:
val = False
break
# assert val == all(my_list)
Upvotes: 8
Reputation: 834
The reason why is already well explained by other answers. As a quick fix you can use:
my_list and all(a==2 for a in my_list)
Upvotes: 1
Reputation: 144
From office documents.
all(iterable)
Return True if all elements of the iterable are true (or if the iterable is empty). Equivalent to:
def all(iterable):
for element in iterable:
if not element:
return False
return True
New in version 2.5.
any(iterable)
Return True if any element of the iterable is true. If the iterable is empty, return False. Equivalent to:
def any(iterable):
for element in iterable:
if element:
return True
return False
New in version 2.5.
Upvotes: 0
Reputation: 532053
Consider a recursive definition of all
:
def all(L):
if L:
return L[0] and all(L[1:])
else:
???
If every element in L
is true, then it must be true that both the first item in L
is true, and that all(L[1:])
is true. This is easy to see for a list with several items, but what about a list with one item. Clearly, every item is true if the only item is true, but how does our recursive formulation work in that case? Defining all([])
to be true makes the algorithm work.
Another way to look at it is that for any list L
for which all(L)
is not true, we should be able to identify at least one element, a
, which is not true. However, there is no such a
in L
when L
is empty, so we are justified in saying that all([])
is true.
The same arguments work for any
. If any(L)
is true, we should be able to identify at least one element in L
that is true. But since we cannot for an empty list L
, we can say that any([])
is false. A recursive implementation of any
backs this up:
def any(L):
if L:
return L[0] or any(L[1:])
else:
return False
If L[0]
is true, we can return true without ever making the recursive call, so assume L[0]
is false. The only way we ever reach the base case is if no element of L
is true, so
we must return False
if we reach it.
Upvotes: 5