Is False == 0 and True == 1 an implementation detail or is it guaranteed by the language?
Asked Answered
G

4

302

Is it guaranteed that False == 0 and True == 1, in Python (assuming that they are not reassigned by the user)? For instance, is it in any way guaranteed that the following code will always produce the same results, whatever the version of Python (both existing and, likely, future ones)?

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

Any reference to the official documentation would be much appreciated!

As noted in many answers, bool inherits from int. The question can therefore be recast as: "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!

Gelasius answered 4/5, 2010 at 9:3 Comment(7)
@S.Lott: There are many reasons to ask the question above. Thus, there are instances where relying on booleans being integer makes your code simpler: do you have to change it? Or, you might spot places in a code written by someone else that relies on booleans being integers: do you interrupt what you are modifying in the code in order to "fix" existing code, or can you rest assured that the current coding is sound? There is a plethora of other examples. More generally, it is good to know the rules of the game, so that you can play it well and program in a sound way.Gelasius
@EOL: can you provide an example of "relying on booleans being integer makes your code simpler"? I can't imagine such a thing. " do you interrupt what you are modifying in the code in order to "fix" existing code, or can you rest assured that the current coding is sound?" The question seems technical, not "how do I cope?" The rules are simple: don't depend on implementation details. So why ask about an implementation detail?Scoop
@S.Lott: The original post precisely echoes your point: the question is essentially "Is this an implementation detail?", because I fully agree with you on the idea that one should not depend on implementation details. If booleans are officially integers of known values, then the code in the question does not rely on implementation details, which is good.Gelasius
@S. Lot: Knowing that False==0 and True==1 makes it easier to count how many bools in a sequence are true: You can just write sum(bool_list). Otherwise, you'd have to write sum(1 for x bool_list if x).Fagin
@dan: That's one way of counting booleans. I would say that bool_list.count(True) is more explicit; it's also about 3 times faster… :)Gelasius
Treating booleans as integers is a type error. If Python had types. I would not make errors in code.Sup
@Sup As the answers show, Python booleans are actually (a specific subclass of) integers. Furthermore, Python obviously has types; maybe you meant that it is "not statically typed"? Also, I am not sure what you mean by "I would not make errors in code". Now, I never like mixing booleans with integers, because they are conceptually different, and I would not mind if Python booleans were not integers, but knowing that they are, with values 0 and 1, is useful.Gelasius
C
239

In Python 2.x this is not guaranteed as it is possible for True and False to be reassigned. However, even if this happens, boolean True and boolean False are still properly returned for comparisons.

In Python 3.x True and False are keywords and will always be equal to 1 and 0.

Under normal circumstances in Python 2, and always in Python 3:

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 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.

There is also, for Python 2:

In numeric contexts (for example when used as the argument to an arithmetic operator), they [False and True] behave like the integers 0 and 1, respectively.

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

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

Cason answered 4/5, 2010 at 9:18 Comment(6)
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'>])Access
Nitpick: any object that provides an __index__ method can be used as a list index; not just subclasses of int or long.Churr
Ah yes, it's there too. But it would be better not to link to the Python 3.0 documentation: 3.0 is dead. :)Churr
Re: "In Python 2.x this is not guaranteed as it is possible for True and False to be reassigned". IMHO, while this is true, anyone who reassigns True or False deserves whatever strange consequences they get. Specifically, storing True before the reassignment and then comparing the result to True after reassignment would break. a = True; True = 'i am an idiot'; a == True => False. Other than such reassignment, the default values are standardized as 0 and 1, and I believe it is common practice to depend on that; e.g. to index into a two-element array, where [0] holds the false case, [1] true.Kamalakamaria
I just noticed another official confirmation of the fact that True can in practice be considered like 1 and False 0: docs.python.org/2/library/stdtypes.html#boolean-values. I'm adding this to this answer.Gelasius
Upvoting for the small shred of hope that Python 4 will fix this. Thanks for that.Smiley
I
87

Here's 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
Insolation answered 4/5, 2010 at 9:16 Comment(1)
Since you give examples of bool conversion, I want to point something out I just ran across that caused a bug in my code bool('0') is TrueDelectate
C
23

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.

Classified answered 4/5, 2010 at 9:33 Comment(4)
Re " True could have any other value. I wouldn't necessarily rely on any guarantee that True==1". Actually, you CAN rely on True==1, as per python.org/dev/peps/pep-0285 , and spec docs.python.org/2/reference/… "Boolean values behave like the values 0 and 1, respectively, in almost all contexts..." I'm not saying it is impossible to override this in Py 2 by reassigning True or False, but I am saying that unless some programmer on your project is an idiot and does such a reassignment, the behavior is guaranteed.Kamalakamaria
BTW sometimes get problem to switch too python style. Examle: ``` if not (2 != 2): # <== thats ok print ("Hello, world!") if ! (1 != 2): # <== SyntaxError print ("Hello, world!") ``` rextester.com/VSTV98648Kinematics
When it says that 0==False is False, does that actually mean that it's 5 ?Gertrudis
This confuses the name False with the value of type bool bound to the name in the builtin scope. The Boolean value is always equal to 0, no matter what value might be assigned to the name.Homovec
K
2

Let's break this question into two parts.

Python:

print(45 == "45")  # Output - False

Javascript:

console.log(45 == "45")  # Output - true

Here, most people think Javascript only checks the value of both side object, But that's not true writing console.log(45 == "45") is similar to print(45 == "45").
But now you have a question if both syntax are similar why do I get different results?

In Javascript :

  • The == operator performs type coercion before comparing the values. This means that JavaScript will attempt to convert the operands to a common type before evaluating the equality.
  • In the case of 45 == "45" in JavaScript, the string "45" is automatically converted to a number because the other operand is a number. JavaScript tries to perform implicit type conversion to make the comparison. The string "45" can be converted to the number 45, and hence the comparison 45 == "45" evaluates to true.
  • Similar to Python keyword is, Javascript has a === Comparison Operator. Which checks both of side object is located in the same computer RAM memory location or not.

In Python :

  • In the Python, 45 and "45" have different types. 45 is an instance of class <integer>, and "45" is an instance of class <string>. They are not instances of the same class.
  • Unlike Javascript, Python doesn't do internal type conversion, So print(45 == "45") evaluates False.
  • Python used internal type conversion, Yes you heard right but here is one condition. Python will use internal type conversion only with boolean type objects.
  • So, in the expression print(True == 1), the boolean value True is implicitly coerced to the integer 1 before performing the comparison. As a result, the comparison print(1 == 1) is evaluated, which is True.
  • When you write print(True == 1) is equivalent to print(1 == 1). When Python interpreter reaches this code of line before executing this code it is convert print(True == 1) to print(int(True) == 1), So finally it becomes print(1 == 1) and now according to == rule both side object value and type <class int> are same hence you see True output in terminal.
  • Similarly, print(False == 0) is equivalent to print(int(False) == 0) and finally print(0 == 0) evaluate to True.

Check HERE.

# Normal behavior
sample_1 = True
print(sample_1) # Output - True
print(int(sample_1)) # Output - 1

sample_2 = False
print(sample_2) # Output - False
print(int(sample_2)) # Output - 0


# Try with True - boolean
A = True + 5  # equivalent to `A = int(True) + 5`
print(A) # Output - 6 (True ---> 1)


# Try with False - boolean
B = False + 5 # equivalent to `A = int(False) + 5`
print(B) # Output - 5 (False ---> 0)


# Try both boolean together
final = False + True # equivalent to `final = int(False) + int(True)`
print(final) # Output - 1  (False ---> 0 & True ---> 1)

Hope it helps everyone!

Kerril answered 29/6, 2023 at 14:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.