[Numpy-discussion] numarray unfriendly to user defined types

Tim Hochberg tim.hochberg at ieee.org
Mon Sep 22 15:28:11 EDT 2003


Hi Todd,

Glad to have you back. I hope you suffered no permanant damage from the 
hurricane. Or the worm for that matter.

Todd Miller wrote:

>On Thu, 2003-09-18 at 19:18, Tim Hochberg wrote:
>  
>
>Sorry for the delay;  I was pretty much shut down by hurricane Isabelle
>from the end of last week.
>
>I hit and bypassed this issue trying to port MA.
>
>  
>
[SNIP]

>Looking in Python's Objects/abstract.c, the function binop1 shows one
>way to squirm around this issue:  subclass from NumArray.   It would be
>interesting to know how Numeric does it.  
>  
>
I think that since Numeric arrays are C classes, they always defer to 
any Python class although I'm not sure of the details. In any event, I'm 
pretty sure it's an accident.

>>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):
>>    
>>
>
>If the "not" belongs there, I'm lost.
>  
>
It does belong there. KnownTypes (perhaps _numarray_nondeferred_types) 
would be a better term) are types that numarray knows that it should 
handle itself. Let me reverse the logic -- maybe it'll be clearer.

    def __mul__(self, operand):
        if isinstance(operand, _numarray_nondeferred_types):
           return operand.__rmul__(self)
        else:
	   try:
              return ufunc.multiply(self, operand)
           except:
              return operand.__rmul__(self)

>I agree with your heuristic,  but I am leery of putting an unqualified
>try/except in front of the numarray ufunc code.  On the other hand,
>qualifying it seems too complicated.  
>  
>
I agree on all counts.

>What about adding a tuple of types to be deferred to?
>
>	def __mul__(self, operand):
>		if isinstance(operand, _numarray_deferred_types):
>			operand.__rmul__(self)
>		else:
>			self.__mul__(operand)
>
>Then other libraries could register classes with something like:
>
>numarray.defer_to(my_class)
>
>which is slightly painful, but avoids masking the ufunc exceptions and
>only needs to be done once for each library base class.  How does that
>sound?
>  
>
I agree that using try/except is probably not worth the danger. However, 
I think I'd prefer the inverse of what you propose. That is:

	def __mul__(self, operand):
		if isinstance(operand, _numarray_nondeferred_types):
                        self.__mul__(operand)
		else:
			operand.__rmul__(self)


and of course a dont_defer_to registration function. Hopefully with a 
better name. The choice comes down to whether we defer by default or 
handle by default. I'm marginally on the side of deferring, but don't 
feel too strongly either way. Either one would be a big improvement.

Perhaps someone else out there has some profound thoughts.

-tim




>Todd
>
>  
>
>>-tim
>>
>>
>>
>>
>>----
>>
>>    
>>
>
>  
>
>>import numarray as na
>>import Numeric as np
>>
>>class Zero:
>>    def __add__(self, other):
>>        return other
>>    __radd__ = __add__
>>zero = Zero()
>>    
>>#~ print zero + np.arange(5)
>>#~ print np.arange(5) + zero
>>#~ print zero + na.arange(5) 
>>#~ print na.arange(5) + zero
>>
>>a = na.arange(5)
>>
>>import copy
>>copy.deepcopy(a)
>>    
>>







More information about the NumPy-Discussion mailing list