While (1) Vs. While(True) -- Why Is There a Difference (In Python 2 Bytecode)?

Intrigued by this question about infinite loops in perl: while (1) Vs. for (;;) Is there a speed difference?, I decided to run a similar comparison in python. I expected that the compiler would generate the same byte code for while(True): pass and while(1): pass, but this is actually not the case in python2.7.

The following script:

import dis

def while_one():
    while 1:
        pass

def while_true():
    while True:
        pass

print("while 1")
print("----------------------------")
dis.dis(while_one)

print("while True")
print("----------------------------")
dis.dis(while_true)

produces the following results:

while 1
----------------------------
  4           0 SETUP_LOOP               3 (to 6)

  5     >>    3 JUMP_ABSOLUTE            3
        >>    6 LOAD_CONST               0 (None)
              9 RETURN_VALUE        
while True
----------------------------
  8           0 SETUP_LOOP              12 (to 15)
        >>    3 LOAD_GLOBAL              0 (True)
              6 JUMP_IF_FALSE            4 (to 13)
              9 POP_TOP             

  9          10 JUMP_ABSOLUTE            3
        >>   13 POP_TOP             
             14 POP_BLOCK           
        >>   15 LOAD_CONST               0 (None)
             18 RETURN_VALUE        

Using while True is noticeably more complicated. Why is this?

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

>>> True == 1
True

>>> True + True
2

Why does while distinguish the two?

I noticed that python3 does evaluate the statements using identical operations:

while 1
----------------------------
  4           0 SETUP_LOOP               3 (to 6) 

  5     >>    3 JUMP_ABSOLUTE            3 
        >>    6 LOAD_CONST               0 (None) 
              9 RETURN_VALUE         
while True
----------------------------
  8           0 SETUP_LOOP               3 (to 6) 

  9     >>    3 JUMP_ABSOLUTE            3 
        >>    6 LOAD_CONST               0 (None) 
              9 RETURN_VALUE         

Is there a change in python3 to the way booleans are evaluated?

1

3 Answers

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.

4

It isn't 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 loop's else clause would never be accessed in Python 3.

And Python 3's 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
James H. Sterling

James H. Sterling

Environmental Science & Climate Journalist

James Sterling reports on renewable energy developments, climate policy, ecological conservation, and green tech innovations around the globe.