[Numpy-discussion] Another suggestion for making numpy's functions generic

Darren Dale dsdale24@gmail....
Tue Oct 20 06:46:42 CDT 2009


On Tue, Oct 20, 2009 at 5:24 AM, Sebastian Walter
<sebastian.walter@gmail.com> wrote:
> I'm not very familiar with the underlying C-API of numpy, so this has
> to be taken with a grain of salt.
>
> The reason why I'm curious about the genericity is that it would be
> awesome to have:
> 1) ufuncs like sin, cos, exp... to work on arrays of any object (this
> works already)
> 2) funcs like dot, eig, etc, to work on arrays of objects( works for
> dot already, but not for eig)
> 3) ufuncs and funcs to work on any objects

I think if you want to work on any object, you need something like the
PEP I mentioned earlier. What I am proposing is to use the existing
mechanism in numpy, check __array_priority__ to determine which
input's __input_prepare__ to call.

> examples that would be nice to work are among others:
> * arrays of polynomials, i.e. arrays of objects
> * polynomials with tensor coefficients, object with underlying array structure
>
> I thought that the most elegant way to implement that would be to have
> all numpy functions try  to call either
> 1)  the class function with the same name as the numpy function
> 2) or if the class function is not implemented, the member function
> with the same name as the numpy function
> 3) if none exists, raise an exception
>
> E.g.
>
> 1)
> if isinstance(x) = Foo
> then numpy.sin(x)
> would call Foo.sin(x) if it doesn't know how to handle Foo

How does it numpy.sin know if it knows how to handle Foo? numpy.sin
will happily process the data of subclasses of ndarray, but if you
give it a quantity with units of degrees it is going to return garbage
and not care.

> 2)
> similarly, for arrays of objects of type Foo:
>  x = np.array([Foo(1), Foo(2)])
>
> Then numpy.sin(x)
> should try to return npy.array([Foo.sin(xi) for xi in x])
> or in case Foo.sin is not implemented as class function,
> return : np.array([xi.sin() for xi in x])

I'm not going to comment on this, except to say that it is outside the
scope of my proposal.

> Therefore, I somehow expected something like that:
> Quantity would derive from numpy.ndarray.
> When calling  Quantity.__new__(cls) creates the member functions
> __add__, __imul__, sin, exp, ...
> where each function has a preprocessing part and a post processing part.
> After the preprocessing call the original ufuncs on the base class
> object, e.g. __add__

It is more complicated than that. Ufuncs don't call array methods, its
the other way around. ndarray.__add__ calls numpy.add. If you have a
custom operation to perform on numpy arrays, you write a ufunc, not a
subclass. What you are proposing is a very significant change to
numpy.

Darren


More information about the NumPy-Discussion mailing list