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...
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?
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.
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:
Must Read
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