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

Nick Coghlan ncoghlan at gmail.com
Tue Sep 13 06:51:25 CEST 2011

On Tue, Sep 13, 2011 at 2:09 PM, Guido van Rossum <guido at python.org> wrote:
> 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__?)

The two issues seem somewhat orthogonal to me, but yes, the general
idea would be to make 'in' behave more like a rich comparison operator
rather than an explicitly boolean operation as it does now.

It occurs to me that adding __in__ could also address a slight
performance oddity with 3.2 range objects: the __contains__ check in
3.2 has an O(1) fast path for containment checks on actual Python
integers, but falls back to the O(n) sequential search for objects
that only implement __index__(). If __in__() was available, such
objects could conceivably map containment tests to checks against the
corresponding real Python integer (although doing that carelessly
would do weird things to other containers, such as identity-keyed
dictionaries. That would be a quality of implementation issue on
__in__ methods, though).

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

I think that's a pretty good explanation for why PEP 335 hasn't been
pushed too hard - there's a lot of value in having not/and/or behave
more like control flow structures rather than ordinary operations. PEP
335 does show that it's theoretically possible to make them behave
more like operators, but that doesn't make it a good idea.

To be honest, I don't think anyone would cry too much if you decided
to explicitly reject it on the basis of continuing to allow control
flow optimisations for code involving not/and/or. While CPython
doesn't do it, I believe there *are* control flow transformations that
the current semantics permit that PEP 335 would disallow, such as
automatically applying De Morgan's Law (I don't actually have a use
case for doing that, I'm just mentioning it as a consequence of the
semantics change proposed by the PEP).


Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia

More information about the Python-ideas mailing list