# 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

As far as your second question about flattening the list, the answer remains the same as the answer I gave yesterday about flattening lists:

2 Likes