The Mastermage
The Mastermage

Reputation: 123

how to overload numpy ufuncs

Im trying to write an error propagation software that works with functions like np.sin(x) i tried implementing my own class like this:

class errör:
    def __init__(self,x,dx):
        self.x = x
        self.dx = dx

    def __add__(self,other):
        return "test"

    def __sin__(self):
        return "works"

but when i try to use this I get:

>>> import numpy as np
>>> np.sin(a)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-4-15dfe0f9a21b> in <module>
----> 1 np.sin(a)

AttributeError: 'errör' object has no attribute 'sin'

why is it telling my that errör doesnt have attribute sin when it does?

Upvotes: 0

Views: 161

Answers (1)

hpaulj
hpaulj

Reputation: 231375

What you are seeing is how Python and object dtype arrays delegate actions:

In [68]: class Foo(): 
    ...:     def __init__(self,val): 
    ...:         self.val = val 
    ...:     def __add__(self, other): 
    ...:         print('add') 
    ...:         return self.val + other 
    ...:     def sin(self): 
    ...:         print('sin') 
    ...:         return np.sin(self.val) 
    ...:     def __repr__(self): 
    ...:         return 'Foo {}'.format(self.val) 
    ...:                                                                        
In [69]: Foo(1)                                                                 
Out[69]: Foo 1
In [70]: Foo(1)+34                                                              
add
Out[70]: 35
In [71]: Foo(1)+Foo(2)                                                          
add
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-71-b4ac926529a7> in <module>
----> 1 Foo(1)+Foo(2)

<ipython-input-68-094444c1c787> in __add__(self, other)
      4     def __add__(self, other):
      5         print('add')
----> 6         return self.val + other
      7     def sin(self):
      8         print('sin')

TypeError: unsupported operand type(s) for +: 'int' and 'Foo'

I didn't define a version of add that handles other objects with type Foo.

Now for the sin delegation:

In [72]: np.sin([Foo(1),Foo(2)])                                                
sin
sin
Out[72]: array([0.8414709848078965, 0.9092974268256817], dtype=object)

An array of Foo objects:

In [73]: np.array([Foo(1),Foo(2)])                                                                        
Out[73]: array([Foo 1, Foo 2], dtype=object)
In [74]: np.array([Foo(1),Foo(2)])+1.23                                                                   
add
add
Out[74]: array([2.23, 3.23], dtype=object)

Upvotes: 1

Related Questions