Skip to content

__numpy_ufunc__ shouldn't disable the default Python binop mechanism #3812

Closed

Description

@pv

If a class has a __numpy_ufunc__ method defined, this disables the usual Python binary operation mechanism, because Numpy's __add__ etc. are implemented via Ufuncs.

Example:

import numpy as np

class Foo(object):
    def __numpy_ufunc__(self, *args, **kw):
        return NotImplemented
    def __add__(self, other):
        return 1
    def __radd__(self, other):
        return 1

x = np.array([1,2,3])
y = Foo()
x + y   

# Traceback (most recent call last):
# TypeError: __numpy_ufunc__ not implemented for this type.

The fix is probably to alter the methods in Numpy's multiarray/number.c so that either (i) the TypeError is caught and converted to NotImplemented, or (ii) a special internal kwarg is passed to the Numpy ufuncs that instructs them to return NotImplemented rather than raising errors.

The problem with (i) is that also other TypeErrors could end up being caught, which may be confusing. (ii) doesn't have this issue, and would allow fixing the issue that ufuncs return NotImplemented in some cases (they shouldn't --- NotImplemented should ever appear only when dealing with Python's binop mechanism).

Activity

  1. pv commented on Sep 28, 2013

    @pv
    MemberAuthor

    Ok, there's a bit more serious point:

    x = np.zeros((3, 3))
    y = csr_matrix(x)
    
    x * y # -> calls np.multiply -> __numpy_ufunc -> elementwise product
    y * x # -> calls csr_matrix.__rmul__ -> matrix product
    

    EDIT: ok, I'm wrong. This doesn't happen, except for in-place multiplication. Moreover, trying to in-place multiply a sparse matrix raises a NotImplementedError, so only one of the above two operations works.

  2. pv commented on Oct 19, 2013

    @pv
    MemberAuthor

    PR merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions