[SciPy-dev] Suppressing of numpy __mul__, __div__ etc

Dag Sverre Seljebotn dagss@student.matnat.uio...
Sun Dec 13 16:05:21 CST 2009


Robert Kern wrote:
> On Sat, Dec 12, 2009 at 14:56, Charles R Harris
> <charlesr.harris@gmail.com> wrote:
>>
>> 2009/12/12 Dmitrey <tmp50@ukr.net>
>>>
>>> hello all,
>>> I have class oofun (in a package FuncDesigner, that is already used by
>>> lots of people) where some operations on numpy arrays (along with
>>> Python
>>> lists and numbers) are overloaded, such as __mul__, __add__, __pow__,
>>> __div__ etc.
>>> There is a problem with numpy arrays: if I use a*f where a is array and
>>> f
>>> is oofun, it returns array with elements a[i]*f. Would it omit calling
>>> array.__mul__ and call only oofun.__rmul__, like it is done in
>>> numpy.matrix
>>> and Python lists/numbers, all would work ok as expected; but now it
>>> makes
>>> FuncDesigner code to work much slower or unexpectedly or doesn't work
>>> at all
>>> instead.
>>> So, does anyone mind if I'll commit some changes to numpy __mul__,
>>> __div__
>>> etc?
>>> I intend to implement the following walkaround:
>>> Now the code looks like this for array:
>>>
>>>     def __mul__(self, i):
>>>         return asarray(multiply(self, i))
>>>
>>> and like this for numpy/matrixlib/defmatrix.py:
>>>
>>>     def __mul__(self, other):
>>>         if isinstance(other,(N.ndarray, list, tuple)) :
>>>             return N.dot(self, asmatrix(other))
>>>         if isscalar(other) or not hasattr(other, '__rmul__') :
>>>             return N.dot(self, other)
>>>         return NotImplemented
>>>
>>> and I want to add an empty class named "CNumpyLeftOperatorOverloaded"
>>> to
>>> numpy, and if someone defines his class as a child of the one, __mul__
>>> and
>>> others will not invoke __div__ etc, calling otherClass.__rdiv__ etc:
>>>
>>>     def __mul__(self, i):
>>>         return asarray(multiply(self, i)) if not
>>> isinstance(i,CNumpyLeftOperatorOverloaded) else i.__rmul__(self)
>>> and declare my class as a child of the one.
>>>
>>> As far as I understood, the changes should be added to
>>> numpy/core/defcherarray.py
>>> So, does anyone mind me to implement it?
>>> D.
>>>
>>
>> Sounds like you are exporting an array interface or subclassing ndarray.
>> If
>> the latter, you might be able to manipulate the value of
>> __array_priority__.
>> I haven't experimented with these things myself.
>
> I don't think he's subclassing ndarray, but does have a class that
> shouldn't be interpreted by ndarray as a scalar. In any case,
> __array_priority__ doesn't matter; it just controls which type the
> output of a multi-input ufunc.
>
>> As to the proposed solutions, they are the start of a slippery slope of
>> trying to identify all objects to which they should apply. I don't think
>> we
>> want to go there.
>
> I think what he is asking for is an empty mixin class which other
> folks could subclass to mark their classes. It would say "Hey,
> ndarray! Let my __mul__, __rmul__, etc., take priority over yours,
> regardless of which of us comes first in the expression." Otherwise,
> ndarray will gladly consume pretty much any object on the other side
> of the operator because it will treat it as an object scalar.
>
> We could also define a standard attribute that could mark such classes
> instead of requiring a mixin subclass.

FWIW, I'd like to submit a patch to Sage for making NumPy arrays and Sage
matrices work better together which would require this functionality. +1
for an attribute and not a mixin, as that would allow Cython classes as
well.

Something like "__do_not_treat_as_scalar__ = True". The idea is simply to
stop ndarray from handling the operation, and let other classes implement
specific support for arithmetic with NumPy arrays. Which is not a slippery
slope at all.

Dag Sverre



More information about the SciPy-Dev mailing list