24

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?

OmnipotentEntity
  • 16,531
  • 6
  • 62
  • 96
quirkystack
  • 1,387
  • 2
  • 17
  • 42
  • 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:15

5 Answers5

43

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.

OmnipotentEntity
  • 16,531
  • 6
  • 62
  • 96
8

"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)
BrianO
  • 1,496
  • 9
  • 12
5

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.

chepner
  • 497,756
  • 71
  • 530
  • 681
1

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)
Joep
  • 788
  • 2
  • 8
  • 23
0

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.

Ch3steR
  • 20,090
  • 4
  • 28
  • 58
rock.liu
  • 113
  • 1
  • 6