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

Brett Cannon bcannon at gmail.com
Tue Sep 20 06:19:16 CEST 2005


On 9/19/05, Raymond Hettinger <raymond.hettinger at verizon.net> wrote:
> 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.
> 

I agree.  While I have used the short-circuiting and the return value
myself, it has often been for just fun one-liners or when it is
extemely simple and I was just too lazy to write out an 'if'
statement.  A conditional operator is much more proper for this (and,
as Guido has said in another email, should be considered as well).

> 
> 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.

Glad the simplification of the bytecode is not the only part of your
proposal.  =)

-Brett


More information about the Python-Dev mailing list