while True or while 1

Steven D'Aprano steve+comp.lang.python at pearwood.info
Mon Jan 23 22:37:46 EST 2012


On Mon, 23 Jan 2012 20:50:11 +0000, Andrea Crotti wrote:

> while 1 works because the 1 is converted to boolean automatically, but
> why not just writing a boolean
> in the first place?

You have misunderstood Python's truth model. It is similar to languages 
like Javascript and PHP, where EVERY object without exception has a truth 
value.

Python does not convert 1 to a boolean, because that would be pointless 
and silly. Bools True and False in Python are no more privileged than 
anything else, in fact they are *less* privileged in Python 2 because 
they are merely built-in names which can be re-bound, not reserved words 
like None.

In Python 2, the peephole optimizer can optimize away constants such as 
1. But 1 itself is not special -- any non-zero int, or non-empty string, 
is also a true-ish value:


>>> from dis import dis
>>> dis(compile('if 42: spam', '', 'exec'))
  1           0 LOAD_NAME                0 (spam)
              3 POP_TOP             
              4 LOAD_CONST               0 (None)
              7 RETURN_VALUE        


While True is just a name, and therefore needs to be looked up at runtime 
like every other name:

>>> dis(compile('if True: spam', '', 'exec'))
  1           0 LOAD_NAME                0 (True)
              3 JUMP_IF_FALSE            8 (to 14)
              6 POP_TOP             
              7 LOAD_NAME                1 (spam)
             10 POP_TOP             
             11 JUMP_FORWARD             1 (to 15)
        >>   14 POP_TOP             
        >>   15 LOAD_CONST               0 (None)
             18 RETURN_VALUE        

In Python 3, True and False become constants, like None, and the peephole 
optimizer can treat them like 42 or 0 or -3. Nevertheless, the important 
factor is not the optimizer, but the JUMP_IF_FALSE op-code. That accepts 
*any* Python object, not just True and False:

>>> dis(compile('if [1, 2, 3]: spam', '', 'exec'))
  1           0 LOAD_CONST               0 (1)
              3 LOAD_CONST               1 (2)
              6 LOAD_CONST               2 (3)
              9 BUILD_LIST               3
             12 JUMP_IF_FALSE            8 (to 23)
             15 POP_TOP             
             16 LOAD_NAME                0 (spam)
             19 POP_TOP             
             20 JUMP_FORWARD             1 (to 24)
        >>   23 POP_TOP             
        >>   24 LOAD_CONST               3 (None)
             27 RETURN_VALUE        


Note that a sufficiently clever peephole optimizer could have recognised 
that [1,2,3] is a true value, just as 42 is a true value. But that's 
besides the point: what is important is that any object is true-ish or 
false-ish.

The only advantages to True and False are:


(1) They satisfy programmers from Pascal and other languages which insist 
on actual Boolean types in comparisons.

You can recognise these people who haven't quite yet grasped Python's 
model, and are still writing Pascal or Java, because they write unpythonic 
code which does unnecessary work, such as "if bool(x)" instead of just 
"if x". Worse are the ones who write "if bool(x) is True", because they 
don't even understand boolean logic.

(2) They are self-documenting, especially for return values. If a 
function returns 0 or 1, there may be some uncertainty whether that 
should be understood as a number, or a flag. By returning False or True, 
it self-documents that it is a flag.

(3) It avoids people having to define their own true/false values, with a 
multitude of spellings, in every library and project that uses them.


If your branch (while loop or if/elif clause) is taking a constant 
literal, you probably should prefer True/False over any other object 
simply because it is more readable and clear as to your intention. But it 
is no big deal if you prefer 1/0 instead.

If you branch over an arbitrary named object, like "while x", there is no 
point in writing that as "while bool(x)". All that does is indicate that 
you are uncomfortable with, or don't understand, Python's truth model, 
and perform an extra, unnecessary, name lookup and function call.



-- 
Steven



More information about the Python-list mailing list