Reputation: 1385
This tripped me up recently in a piece of Python code - I was checking if any of the values in a list were False, so I used something like:
if any(not v for v in values):
# Do something...
However, I forgot that there were None
values in the list, so I kept getting confusing outputs until I remembered to check for that first. That got me wondering though - what's the rationale behind (not None) == True
? None == False
evaluates to False
, so it's not reflexive, and it's not immediately clear to me why the logical negation of the None
object should evaluate to True
.
Upvotes: 1
Views: 2647
Reputation: 1121366
not
is an operator that produces a boolean value, the inverse of the truth value of it's operand.
I suspect you are confusing the truth value with the boolean value. The latter is only either True
or False
, but the truth value of any Python object can be converted to a boolean value by passing it to the bool()
function. Statements like if
and while
, operators like and
, or
and not
test for truth values, not specifically boolean values. any()
and all()
test each value in the iterable for truth as well.
As such, you should never need to do if some_expression == True
or if not some_expression == True
when testing truth values. Just use if some_expression
or if not some_expression
.
Note that not
has to return a boolean value because you can't, usually, invert a truth value. What would the inverse be of 0
or an empty list, for example? 0
is considered false, but any other integer would be considered true, so what value would not 0
return if not False
? For lists, what would you put in the list to produce not []
?
Upvotes: 4
Reputation: 181
This answer to a related question contains some good info you may want to check out, explaining detail about the use of True
, False
, and None
in Python: https://stackoverflow.com/a/9494887/4174975
An explanation that's perhaps more specific to your answer can be found in the O'Reilly book Introducing Python by Bill Lubanovic, who refers to Python programs that use the concept of "truthiness" and "falsiness" to check for empty data structures as well as False
conditions. The author even has a subsection on page 88 titled "None is Useful" which elaborates:
None
is a special Python value that holds a place when there is nothing to say. It is not the same as the boolean valueFalse
, although it looks false when evaluated as boolean. [...] You'll needNone
to distinguish a missing value from an empty value... zero-valued integers or floats, empty string (''), lists([]), tuples((,)), dictionaries({}), and sets(set()) are allFalse
, but are not equal toNone
.
So that is the rationale behind why None
behaves the way that it does, and has subtle qualities apart from what you get with True
and False
or a 1
or a 0
.
As to the other part of your question, it appears to be a logical tautology: None
is False
because Python interprets the None
as being the equivalent of a null
for the reasons found above. By adding not
to a None
, you are inverting its boolean value, which turns it into a True
.
Upvotes: 0
Reputation: 2280
The explanation for why it happens is in the comments to your question. A good way to check if anything within your list evaluates to false is:
if not all(values):
There are many ways to do what you're doing but this for me is more readable than the list comprehension you have.
Upvotes: 0