I am learning python, but I'm a bit confused by the following result.
In [41]: 1 == True
Out[41]: True
In [42]: if(1):
...: print('111')
...:
111
In [43]: ... == True
Out[43]: False <===== why this is False while '1 == True' is True in previous sample
In [44]: if (...): <==== here ... just behaves like True
...: print('...')
...:
...
According to the documentation, ...
has a truth value of True.
But I still feel the above code a bit inconsistent.
...And something more interesting:
In [48]: 2==True
Out[48]: False <===== why 1==True returns True while 2==True returns False?
In [49]: if(2):
...: print('222')
...:
222
You're mixing two concepts: equality testing and truth-value testing. They are not the same in Python.
I think what triggered the question is that Python does an implicit casting when you do if something
(it casts the something to bool
) but it does not do implicit casting when you do something1 == something2
.
Pythons data model actually explains how these operations are done:
__bool__
method and if it does it uses the returned boolean. __bool__
method it looks at the __len__
method. If it's implemented it will use the result of len(obj) != 0
. True
.For integers the __bool__
method returns True
except when the integer value is 0
(then it's False
).
The Ellipsis object (...
is the Ellipsis object) on the other hand doesn't implement __bool__
or __len__
so it's always True
.
Equality testing relies on the __eq__
method of both arguments. It's more a chain of operations:
__eq__
when the second operand is passed as argument.__eq__
when the first operand is passed as argument.The order of these operations may vary.1
For built-in Python types these operations are explicitly implemented. For example int
egers implement __eq__
but the CHECK_BINOP
makes sure that it returns NotImplemented
if the other one isn't an int
eger.
The Ellipsis
object doesn't implement __eq__
at all.
So when you compare integers and Ellipsis Python will always fallback to object identity and so it will always return False
.
On the other hand bool
eans are a subclass of int
egers so they actually compare with int
(they are another int
after all). The booleans are implemented as 1
(True
) and 0
(False
). So they compare equal:
>>> 1 == True
True
>>> 0 == False
True
>>> 1 == False
False
>>> 0 == True
False
Even though the source code is probably hard to understand I hope I explained the concepts well enough (the source code is for the CPython implementation, the implementation in other Python implementations like PyPy, IronPython may differ!). The important take-away message should be that Python doesn't do implicit conversions in equality checks and equality testing is not related to truth value testing at all. The built-in types are implemented that they almost always give senseable results:
truthy
. However if you create your own classes you can override equality and truth value testing as you like (and then you can spread a lot of confusion)!
1 In some cases the order is changed:
__eq__
methods are called. For example when checking if some item is in a list, i.e. 1 in [1,2,3]
.