On Mon, Nov 7, 2016 at 1:08 AM, Ralf Gommers <ralf.gommers@gmail.com> wrote:


On Mon, Nov 7, 2016 at 9:10 AM, Charles R Harris <charlesr.harris@gmail.com> wrote:


On Sun, Nov 6, 2016 at 11:44 AM, Charles R Harris <charlesr.harris@gmail.com> wrote:
Hi All,

For those interested in continuing the __numpy_ufunc__ saga, there is a pull request enabling it. Likely we will want to make some changes up front before merging that, so some discussion is in order.


As a first order of business, let's decide whether to remove the index and rename `__numpy_ufunc__`. The motivation for this is discussed in issue #5986.
If we decide positive on that (I'm in favor),

It seems like everyone on that issue is in favor or at least +0. So +1 from me too.
 
I would be happy with the proposed name `__array_ufunc__`, although something more descriptive like `__handle_ufunc__` might be better.

 
This is a wonderful opportunity for bike shedding for those so inclined ;)

Let me try to break things down an bit.


Uncontroversial

  • Rename __numpy_ufunc__ to __array_ufunc__
  • Remove index
  • Out is always a tuple

I think this much is useful even if nothing else is done.

Goals

  • Deprecate __array_priority__
  • Ufuncs should succeed or error, never return NotImplemented
  • Add __array_ufunc__ stub to ndarray.

I don't think these are controversial either, but they are longer term except possibly the last. Note that never returning NotImplemented disentangles ufuncs from ndarray binops, which I think is a good thing.

Binops


Here we come to the crux of the last arguments. The functions used for binops can currently be set dynamically, the method that is currently used to set them when the ufunc module is loaded. I think we want to do away with that at some point and fix a set of ufuncs with which they are implemented. This allows folks to overide the binop behavior using __array_ufunc__. I think that is mostly of interest to people who are subclassing ndarray and with that restriction doesn't bother me except that it entangles ufuncs with binops. However, what I'd like to see as well is an opt out for objects that don't care about ufuncs, but want to override the python numeric operators, something simple like `__me_me_me__`, or,  more seriously, `__array_opt_out__`  that will only come into play if the defining object is on the right hand side of an instance of ndarray. In that case the binop would return NotImplemented so as to defer to the Python machinery.  Note that  __array_priority__ is currently (ab)used for this.

Numpy scalars

Numpy scalars default to the corresponding PyArray_Type or PyGenericArrType_Type unless both arguments can be converted to the same c type as the calling scalar, so I don't think there is a problem there. Note that they do check _array_priority_ before trying to convert unknown objects to array scalars in a fallback case.

Chuck