while (1) vs. while(True) — Why is there a difference (in python 2 bytecode)?

while (1) vs. while(True) — Why is there a difference (in python 2 bytecode)?

In Python 2.x, True is not a keyword, but just a built-in global constant that is defined to 1 in the bool type. Therefore the interpreter still has to load the contents of True. In other words, True is reassignable:

Python 2.7 (r27:82508, Jul  3 2010, 21:12:11) 
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
Type help, copyright, credits or license for more information.
>>> True = 4
>>> True
4

In Python 3.x it truly becomes a keyword and a real constant:

Python 3.1.2 (r312:79147, Jul 19 2010, 21:03:37) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type help, copyright, credits or license for more information.
>>> True = 4
  File <stdin>, line 1
SyntaxError: assignment to keyword

thus the interpreter can replace the while True: loop with an infinite loop.

It isnt quite right, to call it an infinite loop

thus the interpreter can replace the while True: loop with an infinite loop.

because one can still break out of such a while True: loop. But such a loops else clause would never be accessed in Python 3.

And Python 3s simplifying of the value lookup for True makes it run just as quickly as while 1 in Python 2.

Performance Comparison

Demonstrating the difference in time for a somewhat nontrivial while loop:

Setup

def while1():
    x = 0
    while 1:
        x += 1
        if x == 10:
            break
            
def whileTrue():
    x = 0
    while True:
        x += 1
        if x == 10:
            break

Python 2

>>> import timeit
>>> min(timeit.repeat(while1))
0.49712109565734863
>>> min(timeit.repeat(whileTrue))
0.756627082824707

Python 3

>>> import timeit
>>> min(timeit.repeat(while1))
0.6462970309949014
>>> min(timeit.repeat(whileTrue))
0.6450748789939098

Explanation

To explain the difference, in Python 2:

>>> import keyword
>>> True in keyword.kwlist
False

but in Python 3:

>>> import keyword
>>> True in keyword.kwlist
True
>>> True = true?
  File <stdin>, line 1
SyntaxError: cant assign to keyword

Since True is a keyword in Python 3, the interpreter doesnt have to look up the value to see if someone replaced it with some other value. But since one can assign True to another value in Python 2, the interpreter has to look it up every time.

Conclusion for Python 2

If you have a tight, long-running loop in Python 2, you probably should use while 1: instead of while True:.

Conclusion for Python 3

Use while True: if you have no condition for breaking out of your loop.

while (1) vs. while(True) — Why is there a difference (in python 2 bytecode)?

This is a 7-year-old question that already has a great answer, but a misconception in the question, which isnt addressed in any of the answers, makes it potentially confusing for some of the other questions marked as duplicates.

In other contexts, python acts as though True equals 1:

>>> True == 1
True

>>> True + True
2

Why does while distinguish the two?

In fact, while isnt doing anything different here at all. It distinguishes 1 and True in exactly the same way that the + example does.


Heres 2.7:

>>> dis.dis(True == 1)
  1           0 LOAD_GLOBAL              0 (True)
              3 LOAD_CONST               1 (1)
              6 COMPARE_OP               2 (==)
              9 RETURN_VALUE

>>> dis.dis(True == 1)
  1           0 LOAD_GLOBAL              0 (True)
              3 LOAD_GLOBAL              0 (True)
              6 BINARY_ADD
              9 RETURN_VALUE

Now compare:

>>> dis.dis(1 + 1)
  1           0 LOAD_CONST               1 (2)
              3 RETURN_VALUE

Its emitting a LOAD_GLOBAL (True) for each True, and theres nothing the optimizer can do with a global. So, while distinguishes 1 and True for the exact same reason that + does. (And == doesnt distinguish them because the optimizer doesnt optimize out comparisons.)


Now compare 3.6:

>>> dis.dis(True == 1)
  1           0 LOAD_CONST               0 (True)
              2 LOAD_CONST               1 (1)
              4 COMPARE_OP               2 (==)
              6 RETURN_VALUE

>>> dis.dis(True + True)
  1           0 LOAD_CONST               1 (2)
              2 RETURN_VALUE

Here, its emitting a LOAD_CONST (True) for the keyword, which the optimizer can take advantage of. So, True + 1 doesnt distinguish, for exactly the same reason while True doesnt. (And == still doesnt distinguish them because the optimizer doesnt optimize out comparisons.)


Meanwhile, if the code isnt optimized out, the interpreter ends up treating True and 1 exactly the same in all three of these cases. bool is a subclass of int, and inherits most of its methods from int, and True has an internal integer value of 1. So, whether youre doing a while test (__bool__ in 3.x, __nonzero__ in 2.x), a comparison (__eq__), or arithmetic (__add__), youre calling the same method whether you use True or 1.

Leave a Reply

Your email address will not be published. Required fields are marked *