4

I'm trying to use the __numpy_ufunc__() method explained here in the Numpy v1.11 docs, to override the behavior of numpy ufuncs on a subclass of ndarray, but it never seems to get called. Despite this use case being listed in the guide, I can't find any examples of anyone actually using __numpy_ufunc__(). Has anyone tried this? Here's a minimal example:

# Check python version
import sys
print(sys.version)

3.5.1 |Continuum Analytics, Inc.| (default, Jun 15 2016, 15:32:45)

[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)

# Check numpy version
import numpy as np
print(np.__version__)

1.11.2

# Subclass ndarray as discussed in 
# https://docs.scipy.org/doc/numpy/user/basics.subclassing.html
class Function(np.ndarray):

    # Create subclass object by view
    def __new__(cls):
        obj = np.asarray([1,2,3]).view(cls)
        return obj

    # I'm not even adding anything functionality yet
    def __array_finalize(self,obj): pass

    # Override ufuncs
    def __numpy_ufunc__(ufunc, method, i, inputs, **kwargs):
        print("In PF __numpy_ufunc__")
        # do other stuff here if I want to 
        # and probably need to return a value...

# Create two Functions
f1=Function()
f2=Function()

# Check that they are correctly initialized as Function objects
# not just ndarrays
print(type(f1),type(f2))

⟨class 'main.Function'⟩ ⟨class 'main.Function'⟩

# Add using operator
f1+f2

Function([2, 4, 6])

# Add, explicitly demanding a numpy ufunc
np.add(f1,f2)

Function([2, 4, 6])

Clearly, the subclassing works, and it's using numpy to add arrays behind the scenes. I'm using a new enough version of numpy to employ the __numpy_ufunc__() feature (according to that docs page, it's new in v1.11). But this code never prints out "In PF __numpy_ufunc__". What gives?

Sam Bader
  • 185
  • 7
  • 1
    Strange... I would have expected the documentation to list a `self` argument or say that this should be a `staticmethod` or `classmethod`. – user2357112 supports Monica Jan 05 '17 at 21:20
  • 1
    I don't think `ndarray` has its own `__numpy_ufunc__`, so you probably shouldn't be trying to call it through `super`. – user2357112 supports Monica Jan 05 '17 at 21:21
  • @user2357112 I agree with you on both counts. I'll remove that `super` line since I don't want that issue muddling up the question. – Sam Bader Jan 05 '17 at 21:26
  • 1
    @user2357112 the whole thing appears to be disabled at the moment see [here](https://mail.scipy.org/pipermail/numpy-discussion/2016-November/076248.html), so that would be a case of docs out of sync. Quite annoying, really, I spent quite some time wondering what I was doing wrong – Paul Panzer Jan 26 '17 at 22:51

1 Answers1

2

This functionality has finally been released in Numpy 1.13 under a new name:

__array_ufunc__ added

This is the renamed and redesigned __numpy_ufunc__. Any class, ndarray subclass or not, can define this method or set it to None in order to override the behavior of NumPy’s ufuncs. This works quite similarly to Python’s __mul__ and other binary operation routines. See the documentation for a more detailed description of the implementation and behavior of this new option. The API is provisional, we do not yet guarantee backward compatibility as modifications may be made pending feedback. See the NEP and documentation for more details.

This should resolve this issue.

Community
  • 1
  • 1
Jonas Adler
  • 8,636
  • 2
  • 35
  • 71