any() and all() on empty list?

Steven D'Aprano steve at REMOVEMEcyber.com.au
Thu Mar 30 04:55:23 EST 2006


Duncan Booth wrote:

> Ron Adam wrote:
> 
> 
>>Where we are assembling widgets in a manufacturing plant. Where we don't 
>>want to go to the next step until *all* the sub parts are present.
>>
>>if all(part.status == 'present' for part in unit):
>>     do_release()
>>
>>Oops!  Some empty bins showed up at the next assembly station. ;-)
> 
> 
> I don't see the problem. You only get an empty bin if there is some part 
> assembled from no sub-parts, in which case you wanted an empty bin.

Okay, Ron's example wasn't the best. How about this 
one, from chess:

The intention is to play cautiously if all threatened 
pieces are valuable, and daringly otherwise. Here is 
the obvious, but wrong, code:

if all(piece.value() > 5 for piece in \
     threatened_pieces):
     play_cautiously()
else:
     play_daringly()

It is wrong because it leads to incorrect behaviour 
when there are no threatened pieces at all -- the 
intention is to play daringly by default, except for 
the specific case of there being threatened pieces, all 
of which are high value pieces.

So one correct, but more verbose, way to code this 
would be:

valuable_danger = [piece.value() > 5 for piece in \
     threatened_pieces]
if valuable_danger and all(valuable_danger):
     play_cautiously()
else:
     play_daringly()


Another obvious way of coding this would be to reverse 
the sign of the test like so:

if not any(piece.value() <= 5 for piece in \
     threatened_pieces):
     play_cautiously()
else:
     play_daringly()

In other words, play daringly unless no threatened 
piece is low value. Unfortunately, while this is 
obvious, it also gives the wrong behaviour when there 
are no threatened pieces.



The lesson of this example is that while the standard 
behaviour of any() and all(), as implemented in Python, 
are often, usually, the Right Way to do things, they do 
fail on some occasions, and coders should be aware of 
cases where the assumptions break down.


-- 
Steven.




More information about the Python-list mailing list