35

In Python, the built-in functions all and any return True and False respectively for empty iterables. I realise that if it were the other way around, this question could still be asked. But I'd like to know why that specific behaviour was chosen. Was it arbitrary, ie. could it just as easily have been the other way, or is there an underlying reason?

(The reason I ask is simply because I never remember which is which, and if I knew the rationale behind it then I might. Also, curiosity.)

Josh Lee
  • 171,072
  • 38
  • 269
  • 275
detly
  • 29,332
  • 18
  • 93
  • 152

9 Answers9

48

How about some analogies...

You have a sock drawer, but it is currently empty. Does it contain any black sock? No - you don't have any socks at all so you certainly don't have a black one. Clearly any([]) must return false - if it returned true this would be counter-intuitive.

The case for all([]) is slightly more difficult. See the Wikipedia article on vacuous truth. Another analogy: If there are no people in a room then everyone in that room can speak French.

Mathematically all([]) can be written:

where the set A is empty.

There is considerable debate about whether vacuous statements should be considered true or not, but from a logical viewpoint it makes the most sense:

The main argument that all vacuously true statements are true is as follows: As explained in the article on logical conditionals, the axioms of propositional logic entail that if P is false, then P => Q is true. That is, if we accept those axioms, we must accept that vacuously true statements are indeed true.

Also from the article:

There seems to be no direct reason to pick true; it’s just that things blow up in our face if we don’t.

Defining a "vacuously true" statement to return false in Python would violate the principle of least astonishment.

Community
  • 1
  • 1
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 3
    Clearly Python needs a `FileNotFound` value for just these situations. – detly Jul 18 '10 at 10:07
  • 2
    Also there not any person in the room that can speak French. – Dave Kirby Jul 18 '10 at 10:08
  • 4
    nicely put by a man with more than the average number of arms – John La Rooy Jul 18 '10 at 10:21
  • I understand the concept, but all this says is that it's arbitrary. I was wondering whether there was an authoritative reason why the choice was made the way it was. – detly Jul 18 '10 at 10:23
  • But one of them *does* return `False`. – detly Jul 18 '10 at 10:55
  • @detly: If you prefer to think about it from the implementation point of view as in the you accepted that's fine too, I just find it easier this way. :-P I like to have an analogy. Perhaps some other users prefer to have an analogy so I will leave my answer here to help others. – Mark Byers Jul 18 '10 at 11:13
  • Oh sure, the more information the better. It's an interesting answer, I just preferred the other rationalisation. – detly Jul 18 '10 at 11:52
  • @detly: "all this says is that it's arbitrary". Wrong. All this says that it's *intuitive*. Not arbitrary. When you try the opposite definitions logic stops working intuitively. The point is that there's an alternative to True, False: None. Which makes more philosophical sense but less mathematical sense. – S.Lott Jul 18 '10 at 12:04
  • @S Lott - that comment was made a few revisions ago, since then it's been fleshed out more - I'd certainly agree now. – detly Jul 18 '10 at 12:31
  • 16
    "Are _all_ eleven-legged cats vampires? Yes -- _all_ 0 of them." "Is there _any_ eleven-legged vampire cat? No, there are isn't _any_." – badp Jul 18 '10 at 13:50
  • @badp - I don't think I'll forget that. Not for a while. – detly Jul 18 '10 at 15:26
  • @detly: just wait until people pull rule 34 on it. – badp Jul 18 '10 at 16:02
  • 2
    Thanks for the half hour excursion into wikipedia following vacuous truth. Bertand was quite the ladies man. Hope for the math geeks if they could just find his equation for love. – Martlark Jul 19 '10 at 04:19
22

One property of any is its recursive definition

any([x,y,z,...]) == (x or any([y,z,...]))

That means

x == any([x]) == (x or any([]))

The equality is correct for any x if and only if any([]) is defined to be False. Similar for all.

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
15

I believe all([])==True is generally harder to grasp, so here are a collection of examples where I think that behaviour is obviously correct:

  • A movie is suitable for the hard of hearing if all the dialog in the film is captioned. A movie without dialog is still suitable for the hard of hearing.
  • A windowless room is dark when all the lights inside are turned off. When there are no lights inside, it is dark.
  • You can pass through airport security when all your liquids are contained in 100ml bottles. If you have no liquids you can still pass through security.
  • You can fit a soft bag through a narrow slot if all the items in the bag are narrower than the slot. If the bag is empty, it still fits through the slot.
  • A task is ready to start when all its prerequisites have been met. If a task has no prerequisites, it's ready to start.
Weeble
  • 17,058
  • 3
  • 60
  • 75
  • I like these! Especially the first and last. – detly Apr 17 '12 at 13:37
  • 1
    Couldn't you just as easily say, a windowless room is lit when all the lights inside are turned on. But when there are no lights inside, it is not! – bcb Apr 26 '19 at 10:04
  • 2
    It would be more accurate to say that a windowless room is lit when *any* light inside the room is turned on. – kaya3 Nov 04 '20 at 21:41
5

I think of them as being implemented this way

def all(seq):
    for item in seq:
        if not item:
            return False
    return True

def any(seq):
    for item in seq:
        if item:
            return True
    return False

not sure they are implemented that way though

John La Rooy
  • 295,403
  • 53
  • 369
  • 502
4

Perl 6 also takes the position that all() and any() on empty lists should serve as sane base-cases for their respective reduction operators, and therefore all() is true and any() is false.

That is to say, all(a, b, c) is equivalent to [&] a, b, c, which is equivalent to a & b & c (reduction on the "junctive and" operator, but you can ignore junctions and consider it a logical and for this post), and any(a, b, c) is equivalent to [|] a, b, c, which is equivalent to a | b | c (reduction on the "junctive or" operator -- again, you can pretend it's the same as logical or without missing anything).

Any operator which can have reduction applied to it needs to have a defined behavior when reducing 0 terms, and usually this is done by having a natural identity element -- for instance, [+]() (reduction of addition across zero terms) is 0 because 0 is the additive identity; adding zero to any expression leaves it unchanged. [*]() is likewise 1 because 1 is the multiplicative identity. We've already said that all is equivalent to [&] and any is equivalent to [|] -- well, truth is the and-identity, and falsity is the or-identity -- x and True is x, and x or False is x. This makes it inevitable that all() should be true and any() should be false.

To put it in an entirely different (but practical) perspective, any is a latch that starts off false and becomes true whenever it sees something true; all is a latch that starts off true and becomes false whenever it sees something false. Giving them no arguments means giving them no chance to change state, so you're simply asking them what their "default" state is. :)

hobbs
  • 223,387
  • 19
  • 210
  • 288
3

any and all have the same meaning in python as everywhere else:

  • any is true if at least one is true
  • all is not true if at least one is not true
zvone
  • 18,045
  • 3
  • 49
  • 77
  • @detly On the contrary, what I wrote is pure logic, much older than any programming language. The implementation comes after the logic. – zvone Jul 18 '10 at 16:07
  • 2
    @detly Real-file example: Are there **any** black cats on Mars? No, because there are no cats there. Are **all** cats on Mars black? Yes, every cat on Mars is black. – zvone Jul 18 '10 at 16:36
  • Okay, I see what you mean now. – detly Jul 19 '10 at 00:09
2

This is really more of a comment, but code in comments doesn't work very well.

In addition to the other logical bases for why any() and all() work as they do, they have to have opposite "base" cases so that this relationship holds true:

all(x for x in iterable) == not any(not x for x in iterable)

If iterable is zero-length, the above still should hold true. Therefore

all(x for x in []) == not any(not x for x in [])

which is equivalent to

all([]) == not any([])

And it would be very surprising if any([]) were the one that is true.

steveha
  • 74,789
  • 21
  • 92
  • 117
2

For general interest, here's the blog post in which GvR proposes any/all with a sample implementation like gnibbler's and references quanifiers in ABC.

ars
  • 120,335
  • 23
  • 147
  • 134
2

The official reason is unclear, but from the docs (confirming @John La Rooy's post):

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

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

See also the CPython-implementation and comments.

pylang
  • 40,867
  • 14
  • 129
  • 121