# bool([[None, None], [None, None]]) is True? Why?

I was wondering why

``````any([(None, None), (None, None)])
True
all([(None, None), (None, None)])
True
all([[None, None], [None, None]])
True
bool([[None, None], [None, None]])
True
``````

given that

``````any([None, None, None])
False
``````

It seems to me that the only way to check whether there exists one value, not None, is to flatten the list :

``````any(x for w in [(None, None), (None, None)] for x in w)
False
``````

Is there a quicker way to do it?

The expression:

``````any([None, None, None])
``````

tests each element in turn to see if it is a true value. So it tests:

``````None  # not a true value
None  # not a true value
None  # not a true value
``````

and so returns False.

The expression:

``````any([(None, None), (None, None)])
``````

likewise tests each element in turn to see if it is a true value. So it tests the first element:

``````(None, None)  # a true value
``````

which is a true value, because it is a non-empty tuple. So it returns True.

The rules for what are considered true and false values are:

False values:

• False (of course!)

• zero numbers (0, 0.0, Fraction(0), Decimal(0) etc)

• empty strings and byte-strings “” and b""

• None

• empty containers like (), , {}, set(), frozenset()

• any object where len(obj) returns 0

• any object where the special dunder method `__bool__` returns False.

True values:

• True (of course!)

• all objects by default including:

• non-zero numbers

• non-empty strings and byte-strings

• non-empty containers

• any object where len(obj) returns a non-zero length

• any object where the `__bool__` dunder method returns True.

So it doesn’t matter that your tuple contains false objects like None, the fact that it contains something rather than nothing at all means that it counts as a true value.

3 Likes