[Numpy-discussion] Unexpected output using numpy.ndarray and__radd__

Mark Hoffmann Mark.Hoffmann at dk.manbw.com
Mon Dec 18 06:29:57 CST 2006

I appreciate the answer and the solution suggestion. I see that it is possible to make a work around by subclassing from ndarray. Still, in the "print a+c" statement, I don't understand why a.__add__(c) doesn't return NotImplemented (because ndarray shouldn't recognize the Cyclehist class) and directly call c.__radd__(a) implemented in my Cyclehist class. I tried the exactly same programme using Python 2.4.1 and Scipy 0.3.2 (based on numeric/numarray) and the result of the "print a+c" didn't get nested as I expect.


-----Original Message-----
From: numpy-discussion-bounces at scipy.org [mailto:numpy-discussion-bounces at scipy.org] On Behalf Of Stefan van der Walt
Sent: 18. december 2006 10:36
To: Discussion of Numerical Python
Subject: Re: [Numpy-discussion] Unexpected output using numpy.ndarray and__radd__

Hi Mark

On Mon, Dec 18, 2006 at 08:30:20AM +0100, Mark Hoffmann wrote:
> The following issue has puzzled me for a while. I want to add a 
> numpy.ndarray and an instance of my own class. I define this operation 
> by implementing the methods __add__ and __radd__. My programme (including output) looks like:
> #!/usr/local/bin/python
> import numpy
> class Cyclehist:
>     def __init__(self,vals):
>         self.valuearray = numpy.array(vals)
>     def __str__(self):
>         return 'Cyclehist object: valuearray = '+str(self.valuearray)
>     def __add__(self,other):
>         print "__add__ : ",self,other
>         return self.valuearray + other
>     def __radd__(self,other):
>         print "__radd__ : ",self,other
>         return other + self.valuearray
> c = Cyclehist([1.0,-21.2,3.2])
> a = numpy.array([-1.0,2.2,-2.2])
> print c + a
> print a + c

In the first instance, c.__add__(a) is called, which works fine.  In the second, a.__add__(c) is executed, which is your problem, since you rather want c.__radd__(a) to be executed.  A documentation snippets:

"""For instance, to evaluate the expression x-y, where y is an instance of a class that has an __rsub__() method, y.__rsub__(x) is called if x.__sub__(y) returns NotImplemented.

Note: If the right operand's type is a subclass of the left operand's type and that subclass provides the reflected method for the operation, this method will be called before the left operand's non-reflected method. This behavior allows subclasses to override their ancestors' operations."""

Since a.__add__ does not return NotImplemented, c.__radd__ is not called where you expect it to be.  I am not sure why broadcasting takes place here, maybe someone else on the list can elaborate.

To solve your problem, you may want to look into subclassing ndarrays, as described at http://www.scipy.org/Subclasses.

Numpy-discussion mailing list
Numpy-discussion at scipy.org

More information about the Numpy-discussion mailing list