[Python-Dev] "and" and "or" operators in Py3.0

Raymond Hettinger raymond.hettinger at verizon.net
Tue Sep 20 01:44:32 CEST 2005


I propose that in Py3.0, the "and" and "or" operators be simplified to
always return a Boolean value instead of returning the last evaluated
argument.

1) The construct can be error-prone.  When an error occurs it can be
invisible to the person who wrote it.  I got bitten in published code
that had survived testing and code review:

  def real(self):
    'Return a vector with the real part of each input element'
    # do not convert integer inputs to floats
    return self.map(lambda z: type(z)==types.ComplexType and z.real or
z)

The code fails silently when z is (0+4i).  It took a good while to trace
down a user reported error (when Matlab results disagreed with my matrix
module results) and determine that the real() method contained an error.
Even when traced down, I found it hard to see the error in the code.
Now that I know what to look for, it has not happened again, but I do
always have to stare hard at any "and/or" group to mentally verify each
case.


2) When going back and forth between languages, it is easy to forget
that only Python returns something other than a boolean.


3) Even when it isn't being used, the possibility of non-boolean return
value complicates the bytecode and parser.  To allow for "and/or", the
conditional opcodes leave the tested value on the stack.  In most cases
both branches go directly to a POP_TOP instruction.  Since the POP_TOP
shouldn't be executed twice, the body of the positive branch has to
close with a jump over the other branch even when it is empty.  For
instance, the simplest case:

        if a:
             b

compiles to:

      1           0 LOAD_NAME                0 (a)
                  3 JUMP_IF_FALSE            8 (to 14)
                  6 POP_TOP             

      2           7 LOAD_NAME                1 (b)
                 10 POP_TOP             
                 11 JUMP_FORWARD             1 (to 15)
            >>   14 POP_TOP             
            >>   15 LOAD_CONST               0 (None)
                 18 RETURN_VALUE  

this could be simpler and faster:
    
      1           0 LOAD_NAME                0 (a)
                  3 JUMP_IF_FALSE            8 (to 10)
      2           6 LOAD_NAME                1 (b)
                  9 POP_TOP             
            >>   10 LOAD_CONST               0 (None)
                 13 RETURN_VALUE  


Executive summary.  Returning only Booleans reduces errors, makes the
code easier to review, follows other language norms, and
simplifies/speeds-up the generated code.



Raymond


P.S.  Simplifying "and" and "or" may create a need to introduce a
conditional operator but that is a discussion for another day.



More information about the Python-Dev mailing list