[Python-ideas] Break the dominance of boolean values in boolean context

Guido van Rossum guido at python.org
Tue Sep 13 06:09:09 CEST 2011

On Mon, Sep 12, 2011 at 8:39 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> On Tue, Sep 13, 2011 at 11:40 AM, Devin Jeanpierre
> <jeanpierreda at gmail.com> wrote:
>> Can we not allow things like `a < b` to return non-boolean values,
>> without altering the behaviour of existing Python types?
> We already do. As far as I am aware, the only holdouts are:
> x in a (coerces to bool)
> not a (coerces to bool)
> a and b (doesn't coerce as such, but roughly equivalent to "a if not a else b")
> a or b (doesn't coerce as such, but roughly equivalent to "a if a else b")
> The first case can already be overridden (via __contains__)

But does the C code wrapping it preserve the non-bool value? (IIRC
originally many of these were constrained by the C implementation more
than by any philosophical desire to keep bool pure.)

> and I
> don't believe there's any specific reason for retaining the coercion
> to bool (aside from nobody writing and championing a patch that
> eliminates the restriction).

Oh I see, you are saying that there is no need *in principle*. Agreed
for __contains__. (BTW there is also a need for the reverse operator.
Maybe it could be called __in__?)

> PEP 207 (which added rich comparisons in
> the first place) is silent on the matter - it only talks about the
> comparison and ordering operations.

It wasn't a priority at the time.

> The latter 3 cases are discussed in depth in PEP 335 (Overloadable
> Boolean Operators). Again, I don't believe there's anything
> fundamentally wrong with the idea, but it requires both an up to date
> reference implementation and a champion willing to gather use cases,
> assess the performance impact and generally argue in its favour. We
> don't have the numpy folks knocking down our door asking for
> distributable versions of these operations, after all.

I'm skeptical. It would mean that the compiler no longer has the
option to translate "if not" into a reversal of the control flow; it
must generate code to execute the "not" operator. That seems like a
pessimization. Here's some disassembler output to prove it:

>>> dis.dis(lambda x: 1 if not x else 2)
  1           0 LOAD_FAST                0 (x)
              3 POP_JUMP_IF_TRUE        10
              6 LOAD_CONST               1 (1)
              9 RETURN_VALUE
        >>   10 LOAD_CONST               2 (2)
             13 RETURN_VALUE
>>> dis.dis(lambda x: 1 if x else 2)
  1           0 LOAD_FAST                0 (x)
              3 POP_JUMP_IF_FALSE       10
              6 LOAD_CONST               1 (1)
              9 RETURN_VALUE
        >>   10 LOAD_CONST               2 (2)
             13 RETURN_VALUE

It looks like the same argument cannot be made for 'and' / 'or', so
perhaps those are fine -- though I also expect that there aren't many
use cases. (For all these, I suspect the most common use case is
actually symbolic algebra packages which want to overload operators so
they can return a parse tree instead of an outcome. This works for
regular operators and for comparisons, but not for in, not, and, or.
But I'm not sure I want to pay the price for this flexibility
everywhere where those operators are used in their traditional
meanings. Admittedly I haven't read PEP 335 thoroughly.

--Guido van Rossum (python.org/~guido)

More information about the Python-ideas mailing list