Pritam
Pritam

Reputation: 333

Subclassing a numpy ndarray is not working properly

I am just trying to subclass ndarray to create a special 2x1 vector with attributes x and y.

class Vec(np.ndarray):
    def __new__(cls, x:int, y:int):
        # print('In __new__ with class %s' % cls)
        obj = super().__new__(cls, (2,), np.int16,
                              np.asarray((x,y)), offset=0, strides=None, order=None)
        obj.x = x
        obj.y = y
        return obj
    
    def __array_finalize__(self, obj):
        if obj is None: return
        self.x = getattr(obj, 'x', None)
        self.y = getattr(obj, 'y', None)

a = Vec(1,2)
b = Vec(3,4)
c = a + b
print(c.x, c.y) # results 1 2

what is going wrong?

Upvotes: 1

Views: 88

Answers (1)

Yevhen Kuzmovych
Yevhen Kuzmovych

Reputation: 12130

The problem is that your x and y are just another fields of the Vec object alongside your 2d array. And numpy doesn't know about them, hence doesn't do anything when calling the __add__ a.k.a. +. So x and y should be values in the array, and you can make properties out of them:

class Vec(np.ndarray):
    def __new__(cls, x:int, y:int):
        obj = super().__new__(cls, (2,), np.int16, np.asarray((x,y)),
                              offset=0, strides=None, order=None)
        obj.x = x
        obj.y = y
        return obj
        
    @property
    def x(self):
        return self[0]
        
    @property
    def y(self):
        return self[1]
        
    @x.setter
    def x(self, x):
        self[0] = x
        
    @y.setter
    def y(self, y):
        self[1] = y


a = Vec(1,2)
b = Vec(3,4)
c = a + b
print(c.x, c.y) # results 4 6

Upvotes: 1

Related Questions