-
-
Notifications
You must be signed in to change notification settings - Fork 12.1k
Description
Example:
In [1]: import numpy as np
In [2]: a = np.int64(1)
In [3]: (a > 0) is True
Out[3]: False
Obviously I understand the reason is because is is doing an object comparison and the result of (a > 0) is still type numpy.bool_. However, for scalar bools, this is really annoying bordering on mistake-inviting due to the fact that is and == are almost idiomatically interchangeable for bools in native Python (again, I understand the difference).
There are also odd promotion rules, to wit:
In [4]: b = np.bool_(True)
In [5]: type(b and True)
Out[5]: bool
In [6]: type(True and b)
Out[6]: numpy.bool_
In [7]: type(b or True)
Out[7]: numpy.bool_
In [8]: type(True or b)
Out[8]: bool
In [9]: type(not b)
Out[9]: bool
In [10]: type(~b)
Out[10]: numpy.bool_
It appears __and__ is doing some kind of inverted __or__. Once more, this is understandable, but it introduces many insidious bugs in existing code that already depends on the assumption that bools in Python work a certain way with operators.
Now, suggestion. One possibility, short of simply converting scalar numpy.bool_ to Python bool is at least for operators like __and__, __or__ whose other operand is a Python bool to return always a Python bool. That would at least isolate the "problem" of unexpected behavior to segments of the code where only numpy code is, and therefore visible to the writer, instead of a case where a library writer may return a numpy.bool_ and a library user may use only the return value and Python bools, neither knowing there is some hidden interaction. May I also suggest, so long as they are different, that __repr__ for numpy.bool_ return something like true and false rather than masquerading as internal True and False?