tags:

views:

662

answers:

4

Is it guaranteed that False == 0 and True == 1, in Python? For instance, is it in any way guaranteed that the following code will always produce the same results, whatever the version of Python (existing and in the foreseeable future)?

0 == False  # True
1 == True   # True
['zero', 'one'][False]  # is 'zero'

Any reference to the official documentation would be much appreciated! Other comments would be appreciated too… :)

Edit: As noted in many answers, bool inherits from int. The question can therefore be recast as: "Is this an implementation detail that might change in the future, or does the documentation officially say that programmers can rely on booleans inheriting from integers, with the values 0 and 1?". This question is relevant for writing robust code that won't fail because of implementation details!

+3  A: 

False is a bool. It has a different type. It is a different object from 0 which is an integer.

0 == False returns True because False is cast to an integer. int(False) returns 0

The python documentation of the == operator says (help('==')):

The operators <, >, ==, >=, <=, and != compare the values of two objects. The objects need not have the same type. If both are numbers, they are converted to a common type.

As a consequence False is converted to an integer for the need of the comparison. But it is different from 0.

>>> 0 is False
False

I hope it helps

luc
This isn't quite right: `bool` is a subclass of `int`, so in a very real sense a bool *is* an integer. For example, `isinstance(True, int)` returns True. And the equality check doesn't convert the bool to an int, since no conversion is necessary: it simply calls `int.__cmp__` directly. Note that `bool.__cmp__ is int.__cmp__` also evaluates to `True`.
Mark Dickinson
+6  A: 

Link to the PEP discussing the new bool type in Python 2.3: http://www.python.org/dev/peps/pep-0285/.

When converting a bool to an int, the integer value is always 0 or 1, but when converting an int to a bool, the boolean value is True for all integers except 0.

>>> int(False)
0
>>> int(True)
1
>>> bool(5)
True
>>> bool(-5)
True
>>> bool(0)
False
Erik Cederstrand
+1. I was just about to post a link to the PEP, but you beat me to it!
Mark Dickinson
+12  A: 

Luc's answer is not complete. The False object is of type bool which is a subclass of int:

object
   |
 int
   |
 bool

It is the only reason why in your example, ['zero', 'one'][False] does work. It would not work with an object which is not a subclass of integer, because list indexing only works with integers, or objects that define a __index__ method (thanks mark-dickinson).

Edit:

It is true of the current python version, and of that of Python 3. The docs for python 2.6 and the docs for Python 3 both say:

There are two types of integers: [...] Integers (int) [...] Booleans (bool)

and in the boolean subsection:

Booleans: These represent the truth values False and True [...] 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.

So booleans are explicitly considered as integers in Python 2.6 and 3.

So you're safe until Python 4 comes along. ;-)

Olivier
0 == 0.0 returns True while ['zero', 'one'][0.0] fails. ['zero', 'one'][False] works because bool is a subclass of int. (int.__subclasses__() returns [<type 'bool'>])
luc
Agree that my answer is not complete. :) yours points the right reason I guess
luc
Nitpick: any object that provides an `__index__` method can be used as a list index; not just subclasses of `int` or `long`.
Mark Dickinson
Accepted: good find from the documentation!
EOL
It is still not clearly guaranteed that False==0 and True==1…
EOL
… well, Mark Dickinson found where in the documentation this is guaranteed! Olivier, it would be great if you could add in your response the reference cited in Mark's comment to the original post. :)
EOL
well, it was there on the part of the docs I already quoted. I quote some line later to make it clearer.
Olivier
Ah yes, it's there too. But it would be better not to link to the Python 3.0 documentation: 3.0 is dead. :)
Mark Dickinson
+4  A: 

In Python 2.x, it is not guaranteed at all:

>>> False = 5
>>> 0 == False
False

So it could change. In Python 3.x, True, False, and None are reserved words, so the above code would not work.

In general, with booleans you should assume that while False will always have an integer value of 0 (so long as you don't change it, as above), True could have any other value. I wouldn't necessarily rely on any guarantee that True==1, but on Python 3.x, this will always be the case, no matter what.

Daniel G
I edited your code (`0 == False` instead of `0 == True`, right?).
Tim Pietzcker
*/me goes and writes a virus to change False on all Python installs on Windows to -3*. Mwahaha!
bradlis7