[Numpy-discussion] numarray unfriendly to user defined types

Tim Hochberg tim.hochberg at ieee.org
Thu Sep 18 16:20:02 CDT 2003


I've run into another issue in my attempt to transition over to 
numarray: it's less friendly to user defined types than Numeric. I think 
this is mainly accidental friednliness on Numeric's part, but it's handy 
nonetheless. The attached file illustrates the issue. Given some object, 
in this case *zero*, that a numarray array does not now how to handle, 
it ends up raising an exception instead of giving the object a chance to 
try. Thus ``zero + numarray.arange(5)`` works while ``numarray.arange(5) 
+ zero`` fails, since in the first case Zero.__add__ is called first, 
while in the second NumArray.__add__ is called first.

This should probably be fixed, but it's not clear what the best way is. 
My first thought was to always give the other object a chance to use 
__rop__ first. This is simple and easy to explain, but fails miserably 
in the common case of multiplying a list and an array. Just to be 
concrete, __mul__ would be replaced by::

    def __mul__(self, operand):
        try:
            return operand.__rmul__(self)
        except:
            return ufunc.multiply(self, operand)

Next thought is to catch exceptions when they occur in numarray and then 
give the other operand a chance::

    def __mul__(self, operand):
        try:
           return ufunc.multiply(self, operand)
        except:
            return operand.__rmul__(self)

This appears like it would fix my particular problem, but still is not 
ideal. Since numarray is the base of libraries that it will know nothing 
about, it should defer to classes it doesn't know about whenever 
possible. Otherewise it's not possible (or maybe just hard)  to create  
new classes that try to be clever, but still interact with numarray in a 
reasonable way. In my case I'm thinking of proxy objects that don't do 
some computations till they are actually required. So my current 
thinking is that __mul__ and friends would be best implemented as::

    def __mul__(self, operand):
        if not isinstance(operand, knownTypes):
            try:
                  return ufunc.multiply(self, operand)
            except:
                pass
        return operand.__rmul__(self)

Where knownTypes is something like (int, long, float, complex, tuple, list).

Anyway, that's my excessively long two cents on this.

-tim




-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: unfriendly.py
Url: http://projects.scipy.org/pipermail/numpy-discussion/attachments/20030918/b12aebe9/attachment.pl 


More information about the Numpy-discussion mailing list