If not ''
evaluates to True
, why does '' == False
evaluates to False
?
For example, the "voids" of the other types (e.g. 0, 0.0) will return True
when compared to False
:
>>> 0 == False
True
>>> 0.0 == False
True
Thanks
If not ''
evaluates to True
, why does '' == False
evaluates to False
?
For example, the "voids" of the other types (e.g. 0, 0.0) will return True
when compared to False
:
>>> 0 == False
True
>>> 0.0 == False
True
Thanks
In the context of Boolean operations, and also when expressions are used by control flow statements, the following values are interpreted as false:
False
,None
, numeric zero of all types, and empty strings and containers (including strings, tuples, lists, dictionaries, sets and frozensets). All other values are interpreted as true. User-defined objects can customize their truth value by providing a__bool__()
method.The operator
not
yieldsTrue
if its argument is false,False
otherwise.https://docs.python.org/3/reference/expressions.html#comparisons
But:
The operators
<
,>
,==
,>=
,<=
, and!=
compare the values of two objects. The objects do not need to have the same type....
Because all types are (direct or indirect) subtypes of
object
, they inherit the default comparison behavior fromobject
. Types can customize their comparison behavior by implementing rich comparison methods like__lt__()
...https://docs.python.org/3/reference/expressions.html#boolean-operations
So, the technical implementation answer is that it behaves the way it does because not
and ==
use different comparisons. not
uses __bool__
, the "truth value" of an object, while ==
uses __eq__
, the direct comparison of one object to another. So it's possible to ask an object whether it considers itself to be truthy or falsey, and separately from that ask it whether it considers itself to be equal to another object or not. The default implementations for that are arranged in a way that two objects can both consider themselves falsey yet not consider themselves equal to one another.
It doesn't make sense for ''
and []
to actually equal False
, because they are clearly different values: a string and a list. If they both equalled False
they would have to be equal to each other*. They are just "falsey", which means they come out as false when they are converted to a boolean.
(* in any sensibly constructed language)
not
is an operation that returns a boolean. Which boolean it returns depends on whether the operand is falsey or not. So not x
is not equivalent to x==False
; it is equivalent to bool(x)==False
.
Such a comparison isn't "Pythonic" (i.e. it isn't what an experienced Python programmer would naturally do). The Pythonic way to proceed is to use a value in a Boolean context such as an if
statement, and leave the interpreter to apply the bool
built-in invisibly to determine a True
or False
value. That's why people commonly write code such as
if lst:
print(headers)
for item in lst:
print(item.format())
else:
print(no_data_message)
rather than using the commonly-seen but less Pythonic if len(lst):
or the even clumsier but still functionally correct if len(lst) > 0:
.
In some respects unfortunately, Python's designer decided that True
and False
would be instances of the bool
type, and that bool
would be a subclass of int
. As a result of this True
compares equal to 1
and False
compares equal to 0
. Numerical conversion accounts for the floating-point (and, for that matter, complex) result.
But just because a bool(x) == True
doesn't mean x == True
, any more than bool(x) == False
implies x == False
. There are many other values that evaluate false, the best-known being
None
There's no way they can all be equal to each other!
Because int(False) == 0
and int(True) == 1
. This is what Python is doing when it tries to evaluate 0 == False
.
On the other hand, bool('') == False
. The same goes for bool([])
and bool({})
.
The fact that x
evaluates to True
doesn't necessarily mean that x == True
.
If you want to check the official explanation, just cast your values like this:
print(bool(None) == False)
print(False == False)
print(bool(0) == False)
print(bool(0.0) == False)
print(bool(0j) == False)
print(bool('') == False)
print(bool(()) == False)
print(bool([]) == False)
print(bool({}) == False)