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\')
...:
I believe it's 1 == True
here is that's weird, not that ... != True
.
1
equals with True
because in Python booleans are subclass of integers (because of PEP-285). See yourself:
>>> issubclass(bool, int)
True
Any object can be tested for "truthiness":
Any object can be tested for truth value, for use in an if or while condition or as operand of the Boolean operations below. The following values are considered false:
None
False
zero of any numeric type, for example, 0, 0.0, 0j.
any empty sequence, for example, '', (), [].
any empty mapping, for example, {}.
instances of user-defined classes, if the class defines a bool() or len() method, when that method returns the integer zero or bool value False. [1]
All other values are considered true — so objects of many types are always true.
Operations and built-in functions that have a Boolean result always return 0 or False for false and 1 or True for true, unless otherwise stated. (Important exception: the Boolean operations or and and always return one of their operands.)
So it's not hard to see that if ...
will enter the branch. The Ellipsis
object is considered true
. However that doesn't mean it has to be equal to True
. Just the bool(...) == True
!
The if
will implicitly call bool
on the condition, so:
if ...:
# something
will be evaluated as if you had written:
if bool(...):
# something
and:
>>> bool(...)
True
>>> bool(1)
True
>>> bool(2)
True
However there's one catch here. True
is equal to 1
and False
equal to 0
, but that's just because bool
subclasses int
eger in python.
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 integers 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]
.In python most (all?) objects have a bool
value. The meaning behind "has a truth value of True" means that bool(obj)
evaluates to True.
On the other hand, True
is treated as 1
in many cases (and False
as 0
) which you can see when you do stuff like:
sum([True, True, False])
# (1 + 1 + 0) -> 2
That is why you get 1 == True
--> True
There is a more explicit explanation in the documentation:
Boolean values are the two constant objects False and True. They are used to represent truth values (although other values can also be considered false or true). In numeric contexts (for example when used as the argument to an arithmetic operator), they behave like the integers 0 and 1, respectively
From the type-hierarchy itself in the docs:
These represent the truth values False and True. The two objects representing the values False and True are the only Boolean objects. The Boolean type is a subtype of the integer type, and Boolean values behave like the values 0 and 1, respectively, in almost all contexts, the exception being that when converted to a string, the strings "False" or "True" are returned, respectively.