[Numpy-discussion] ndarray.__mul__ is too gready?

Eike Welk eike.welk@gmx....
Thu Apr 24 17:21:37 CDT 2008


Just for the record, because I had a very similar problem:

On Wednesday 23 January 2008 12:11, Pearu Peterson wrote:
> Users may accidentally hit vector * matrix and this should raise
> an exception. But when vector is numpy array, then ndarray.__mul__
> calls element * A for each array element and here A.__rmul__
> gets only the types of array elements (that are floats, for
> instance) as rhs and hence is not able to decide that it should
> return NotImplemented. Instead, it computes scalar * matrix and
> the final result will be
>   array([element1*matrix, element2*matrix, ..])
> which is not desired already because of the memory usage and
> should have raised an exception instead.
>
> Here is a small example illustrating the problem:
>
> class A:
>     def __rmul__(self, other):
>         if isinstance(other, ndarray):
>             return NotImplemented
>         if isinstance(other, (int, float)):
>             return self # pretend other==1 for an example
>         return NotImplemented
>
>     def __repr__(self): return 'A()'
>
> >>> array([1,2,3]) * A()
>
> array([A(), A(), A()], dtype=object)
> # expected TypeError
>
> Is there any workaround to this problem?
> In other situations/applications the above behavior of
> ndarray.__mul__ is a feature but is there any way to
> avoid this feature?
>

The class attribute __array_priority__ seems to control what exactly 
happens when those special functions are called. It is said to be 
documented in Travis Oliphant's Numpy book. Writing 
__array_priority__ = 10.0 should do what you want. 

So, the class definition should look like this:

class A(object):
    __array_priority__ = 10.0

    def __rmul__(self, other):
        ... <smart code here> ...

> Thanks,
> Pearu

Kind regards,
Eike.


More information about the Numpy-discussion mailing list