[Python-ideas] Changing the meaning of bool.__invert__

Nathaniel Smith njs at pobox.com
Fri Apr 8 03:34:06 EDT 2016

On Thu, Apr 7, 2016 at 11:54 PM, Greg Ewing <greg.ewing at canterbury.ac.nz> wrote:
> Terry Reedy wrote:
>> Given that ~bool hardly make any sense currently, I would not expect it to
>> be in much use now.  Hence not much to break.
> But conversely, any code that *is* using ~bool instead of
> "not bool" is probably doing it precisely because it
> *does* want the integer interpretation.

It would be interesting actually if anyone has any idea of how to get
some empirical data on this -- it isn't actually clear to me whether
this is true or not.

The reason I'm uncertain is that in numpy code, using operations like
~ on booleans is *very* common, because the whole idea of numpy is
that it gives you a way to write code that works the same on either a
single value or on an array of values, and when you're working with
booleans then this means you have to use '~': '~' works on arrays and
'not' doesn't.

And, for numpy bools or arrays of bools, ~ does logical negation:

In [1]: ~np.bool_(True)
Out[1]: False

So you can write code like:

# Contrived function that doubles 'value' if do_double is true
# and otherwise halves it
def double_or_halve(value, do_double):
    value = np.asarray(value)
    value[do_double] *= 2
    value[~do_double] *= 0.5
    return value

and then this works correctly if 'do_double' is a numpy bool or array of bools:

In [16]: double_or_halve(np.arange(3, dtype=float), np.array([True,
False, True]))
Out[16]: array([ 0. ,  0.5,  4. ])

In [21]: double_or_halve(5.0, np.bool_(False))
Out[21]: array(2.5)

But if you pass in a regular Python bool then the attempt to index by
~do_double turns into negative integer indexing and blows up:

In [23]: double_or_halve(5.0, False)
IndexError: too many indices for array

Of course this is a totally contrived function, and anyway it has a
bug -- the user should have said 'do_double = np.asarray(do_double)'
at the top of the function, and that would fix the problem. This is
definitely not some massive problem afflicting numerical users, and I
don't have any strong opinion on Antoine's proposal.

But, it is the only case where I can imagine someone intentionally
writing ~bool, so it actually strikes me as plausible that the
majority of existing code that writes ~bool is like this: doing it by
mistake and expecting it to be the same as 'not'.



Nathaniel J. Smith -- https://vorpus.org

More information about the Python-ideas mailing list