True, False, None (was re. Pruss's manifesto)

Alex Martelli aleax at aleax.it
Mon Nov 10 17:11:53 EST 2003


Ron Adam wrote:
   ...
> Is it possible to make the argument optional for while?  That may

Yes, it is technically possible -- you'd need to play around with the
Dreaded Grammar File, but as Python grammar tasks go this one seems
simple.

> allow for an even faster time?

No, there is no reason why "while 1:", "while True:" once True is
a keyword, and "while:" were the syntax extended to accept it, could
or should compile down to code that is at all different.

> while:
> <instructions>
> 
> It would be the equivalent as making the default argument for while
> equal to 1 or True.  Could it optimize to single cpu instruction when
> that format is used?  No checks or look ups at all?

"while 1:" is _already_ compiled to a single (bytecode, of course)
instruction with "no checks or look ups at all".  Easy to check:

>>> x=compile('while 1: foop()', '<str>', 'exec')
>>> dis.dis(x)
  1           0 SETUP_LOOP              19 (to 22)
              3 JUMP_FORWARD             4 (to 10)
              6 JUMP_IF_FALSE           11 (to 20)
              9 POP_TOP
        >>   10 LOAD_NAME                0 (foop)
             13 CALL_FUNCTION            0
             16 POP_TOP
             17 JUMP_ABSOLUTE           10
        >>   20 POP_TOP
             21 POP_BLOCK
        >>   22 LOAD_CONST               1 (None)
             25 RETURN_VALUE

the four bytecodes from 10 to 17 are the loop: name 'foop'
is loaded, it's called with no argument, its result is
discarded, and an unconditional jump back to the first of
these steps is taken (this loop, of course, will only get
out when function foop [or the lookup for its name] cause
an exception).  (The 2 opcodes at 6 and 9 never execute,
and the opcode at 3 could be eliminated if those two were,
but that's the typical kind of job for a peephole optimizer,
an easy but low-returns project).

Note the subtle difference when we use True rather than 1:

>>> x=compile('while True: foop()', '<str>', 'exec')
>>> dis.dis(x)
  1           0 SETUP_LOOP              19 (to 22)
        >>    3 LOAD_NAME                0 (True)
              6 JUMP_IF_FALSE           11 (to 20)
              9 POP_TOP
             10 LOAD_NAME                1 (foop)
             13 CALL_FUNCTION            0
             16 POP_TOP
             17 JUMP_ABSOLUTE            3
        >>   20 POP_TOP
             21 POP_BLOCK
        >>   22 LOAD_CONST               0 (None)
             25 RETURN_VALUE

_Now_, the loop runs all the way through the bytecodes
from 3 to 20 included (the opcodes at 0 and 21 surround
it just like they surrounded the unconditional loop we
just examined).  Before we can get to the "real job" of
bytecodes 10 to 17, each time around the loop, we need
to load the value of name True (implying a lookup), do
a conditional jump on it, otherwise discard its value.

If True was a keyword, the compiler could recognize it and
generate just the same code as it does for "while 1:" --
or as it could do for "while:", were that extension of
the syntax accepted into the language.


As to the chances that a patch, implementing "while:" as
equivalent to "while 1:", might be accepted, I wouldn't
be particularly optimistic.  Still, one never knows!


Alex





More information about the Python-list mailing list