'Subclassing ndarray: what is the purpose of passing parameters declared in __new__ also in __array_finalize__?

I'm creating a class that inherit from numpy.ndarray.

Here is the suggestion of the documentation:

class RealisticInfoArray(np.ndarray):

    def __new__(cls, input_array, info=None):
        # Input array is an already formed ndarray instance
        # We first cast to be our class type
        obj = np.asarray(input_array).view(cls)
        # add the new attribute to the created instance
        obj.info = info
        # Finally, we must return the newly created object:
        return obj

    def __array_finalize__(self, obj):
        # see InfoArray.__array_finalize__ for comments
        if obj is None: return
        self.info = getattr(obj, 'info', None)

When I call:

rarr = RealisticInfoArray([1,2,3,4,5,6], info='This is a realistic array')
rarr.info

It works:

'This is a realistic array'

And if I call:

rarr = RealisticInfoArray([1,2,3,4,5,6])
rarr.info

It works:

None

First observation

If I delete the def array_finalize part, it still works the same.

Second observation

If I replace:

self.info = getattr(obj, 'info', 'default value')

And if I call:

rarr = RealisticInfoArray([1,2,3,4,5,6])
rarr.info

It does not update the default value:

None

This seems pretty normal the self of the array_finalize is the one of the underlying numpy array and not the one of the new instance...

Third observation

We can easily verify this by not providing any default value:

def __array_finalize__(self, obj):
        # see InfoArray.__array_finalize__ for comments
        if obj is None: return
        self.info = getattr(obj, 'info')
rarr = RealisticInfoArray([1,2,3,4,5,6], info='This is a realistic array')
rarr.info

---> 17 self.info = getattr(obj, 'info')

AttributeError: 'numpy.ndarray' object has no attribute 'info'

So it seems that we are feeding the self of the underlying numpy array with the default values. But it does nothing regarding the instance of the new class. Also, we don't actually pass value settled in the instance declaration.

So, why do we need to do that?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source