You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
BUG: ndarray.__eq__ does not respect overrides for void #9153
As noted in #9147, ndarray.__eq__ special-cases void arrays, which means that array-likes cannot use __array_ufunc__or __array_priority__ to override it:
class B(object):
def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
return 'B!'
def __eq__(self, other):
return 'B==B'
b = B()
x = np.array([(0, 1, 0)] * 10, dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])
b == x
# 'B==B'
x == b
# FutureWarning: elementwise == comparison failed and returning scalar instead;...
# False
EDIT: the above also means array-like's cannot override via __array_priority__ either.
EDIT 2: For subclasses, the situation is better. If they override __eq__, that will just get called by python. If they do not, things still work more or less, since the code gets elements from the arrays, and compares those using np.equal and combines the results using np.logical_and, both of which do get overridden with __array_ufunc__.
EDIT 3: Crossed out text above reflects #9167, which moves RICHCMP_GIVE_UP_IF_NEEDED and thus solves __array_priority__ and __array_ufunc__ = None, but not a properly defined __array_ufunc__ like the example above.
changed the title [-]BUG: ndarray.__eq__ does not respect __aray_ufunc__ for void[/-][+]BUG: ndarray.__eq__ does not respect overrides for void[/+]on May 21, 2017
Note: Since np.equal cannot deal with void, the expectation in this case is not, I think, that __array_ufunc__ is called, since any array-like cannot count on being able to call np.equal. But at least ndarray.__eq__ should return NotImplemented in this case (or the case where B.__array_priority__ is high), to give B.__eq__ a chance.
Was about to make a PR, but then I realized my logic won't quite work: currently, the way binop_should_defer is written is that if __array_ufunc__ is present, the operation is not deferred, because the idea is that np.equal will be called anyway, which will transfer to __array_ufunc__. But of course in the case at hand, np.equal does not get called.
Is there a reason that the special handling of == is currently in array_richcompare, and not in ufunc.__call__? It'd still be a hack, but we might as well put it in a place that catches everything, right?
To have it in the ufunc, wouldn't __call__ have to check for void for all ufuncs even though it is only available for equal and not_equal? Or might it be as (relatively) simple as defining an inner loop for void type only for those two?
It would solve the __array_priority__ and __array_ufunc__=None override problems though. That would be a good start and something I wouldn't mind having in 1.13.
@charris - OK, that makes sense: a PR just covering the high array priority and array ufunc is None case is in #9167. If we go that route, what remains will just be for an array like that defines __array_ufunc__ as a proper function; probably best to open a new issue for it (once #9167 is in).
Updated the text at the top to reflect that even with #9167 the issue remains that an array-like cannot override __eq__ for structured arrays by using __array_ufunc__.
Activity
[-]BUG: ndarray.__eq__ does not respect __aray_ufunc__ for void[/-][+]BUG: ndarray.__eq__ does not respect overrides for void[/+]mhvk commentedon May 21, 2017
Note: Since
np.equalcannot deal with void, the expectation in this case is not, I think, that__array_ufunc__is called, since any array-like cannot count on being able to callnp.equal. But at leastndarray.__eq__should returnNotImplementedin this case (or the case whereB.__array_priority__is high), to giveB.__eq__a chance.charris commentedon May 21, 2017
That looks correct to me.
charris commentedon May 21, 2017
@njsmith Comment?
charris commentedon May 23, 2017
@mhvk Want to make the PR or should I do it?
mhvk commentedon May 23, 2017
Was about to make a PR, but then I realized my logic won't quite work: currently, the way
binop_should_deferis written is that if__array_ufunc__is present, the operation is not deferred, because the idea is thatnp.equalwill be called anyway, which will transfer to__array_ufunc__. But of course in the case at hand,np.equaldoes not get called.I'm not quite sure how to fix this...
eric-wieser commentedon May 23, 2017
Is there a reason that the special handling of
==is currently inarray_richcompare, and not inufunc.__call__? It'd still be a hack, but we might as well put it in a place that catches everything, right?mhvk commentedon May 23, 2017
To have it in the
ufunc, wouldn't__call__have to check forvoidfor all ufuncs even though it is only available forequalandnot_equal? Or might it be as (relatively) simple as defining an inner loop for void type only for those two?charris commentedon May 23, 2017
It would solve the
__array_priority__and__array_ufunc__=Noneoverride problems though. That would be a good start and something I wouldn't mind having in 1.13.mhvk commentedon May 23, 2017
@charris - OK, that makes sense: a PR just covering the high array priority and array ufunc is None case is in #9167. If we go that route, what remains will just be for an array like that defines
__array_ufunc__as a proper function; probably best to open a new issue for it (once #9167 is in).mhvk commentedon May 26, 2017
Updated the text at the top to reflect that even with #9167 the issue remains that an array-like cannot override
__eq__for structured arrays by using__array_ufunc__.mhvk commentedon Jan 11, 2024
Closing this, since it is possible to avoid by setting
__array_ufunc__ = Noneto explicitly opt out ofndarray.__eq__taking over.