[Numpy-discussion] numpy.trapz() doesn't respect subclass
Darren Dale
dsdale24@gmail....
Sun Mar 28 02:29:30 CDT 2010
On Sat, Mar 27, 2010 at 10:23 PM, <josef.pktd@gmail.com> wrote:
> subclasses of ndarray, like masked_arrays and quantities, and classes
> that delegate to array calculations, like pandas, can redefine
> anything. So there is not much that can be relied on if any subclass
> is allowed to be used inside a function
>
> e.g. quantities redefines sin, cos,...
> http://packages.python.org/quantities/user/issues.html#umath-functions
Those functions were only intended to be used in the short term, until
the ufuncs that ship with numpy included a mechanism that allowed
quantity arrays to propagate the units. It would be nice to have a
mechanism (like we have discussed briefly just recently on this list)
where there is a single entry point to a given function like add, but
subclasses can tweak the execution.
We discussed the possibility of simplifying the wrapping scheme with a
method like __handle_gfunc__. (I don't think this necessarily has to
be limited to ufuncs.) I think a second method like __prepare_input__
is also necessary. Imagine something like:
class GenericFunction:
@property
def executable(self):
return self._executable
def __init__(self, executable):
self._executable = executable
def __call__(self, *args, **kwargs):
# find the input with highest priority, and then:
args, kwargs = input.__prepare_input__(self, *args, **kwargs)
return input.__handle_gfunc__(self, *args, **kwargs)
# this is the core function to be passed to the generic class:
def _add(a, b, out=None):
# the generic, ndarray implementation.
...
# here is the publicly exposed interface:
add = GenericFunction(_add)
# now my subclasses
class MyArray(ndarray):
# My class tweaks the execution of the function in __handle_gfunc__
def __prepare_input__(self, gfunc, *args, **kwargs):
return mod_input[gfunc](*args, **kwargs)
def __handle_gfunc__(self, gfunc, *args, **kwargs):
res = gfunc.executable(*args, **kwargs)
# you could have called a different core func there
return mod_output[gfunc](res, *args, **kwargs)
class MyNextArray(MyArray):
def __prepare_input__(self, gfunc, *args, **kwargs):
# let the superclass do its thing:
args, kwargs = MyArray.__prepare_input__(self, gfunc, *args, **kwargs)
# now I can tweak it further:
return mod_input_further[gfunc](*args, **kwargs)
def __handle_gfunc__(self, gfunc, *args, **kwargs):
# let's defer to the superclass to handle calling the core function:
res = MyArray.__handle_gfunc__(self, gfunc, *args, **kwargs)
# and now we have one more crack at the result before passing it back:
return mod_output_further[gfunc](res, *args, **kwargs)
If a gfunc is not recognized, the subclass might raise a
NotImplementedError or it might just pass the original args, kwargs on
through. I didn't write that part out because the example was already
running long. But the point is that a single entry point could be used
for any subclass, without having to worry about how to support every
subclass.
Darren
More information about the NumPy-Discussion
mailing list