Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheritage from ndarray calls __getitem__

Tags:

python

numpy

Hi I'm trying to derive a class from ndarray. I'm sticking to the recipe found in docs but I get an error I do not understand, when I override a __getiem__() function. I'm sure this is how it is supposed to work but I do not understand how to do it correctly. My class that basically adds a "dshape" property looks like:

class Darray(np.ndarray):
    def __new__(cls, input_array, dshape, *args, **kwargs):
        obj = np.asarray(input_array).view(cls)
        obj.SelObj = SelObj
        obj.dshape = dshape
        return obj

    def __array_finalize__(self, obj):
        if obj is None: return
        self.info = getattr(obj, 'dshape', 'N')  

    def __getitem__(self, index):        
        return self[index]

when I now try to do:

D = Darray( ones((10,10)), ("T","N"))

the interpreter will fail with a maximum depth recursion, because he calls __getitem__ over and over again.

can someone explain to me why and how one would implement a getitem function?

cheers, David

like image 200
Magellan88 Avatar asked Oct 10 '13 20:10

Magellan88


People also ask

What Ndarray called?

An ndarray is a (usually fixed-size) multidimensional container of items of the same type and size. The number of dimensions and items in an array is defined by its shape , which is a tuple of N non-negative integers that specify the sizes of each dimension.

Is Ndarray and array the same?

array is just a convenience function to create an ndarray ; it is not a class itself. You can also create an array using numpy. ndarray , but it is not the recommended way. From the docstring of numpy.

What is the use of Ndarray?

NumPy aims to provide an array object that is up to 50x faster than traditional Python lists. The array object in NumPy is called ndarray , it provides a lot of supporting functions that make working with ndarray very easy. Arrays are very frequently used in data science, where speed and resources are very important.

What is the Ndarray class?

The ndarray object consists of contiguous one-dimensional segment of computer memory, combined with an indexing scheme that maps each item to a location in the memory block. The memory block holds the elements in a row-major order (C style) or a column-major order (FORTRAN or MatLab style).


2 Answers

can someone explain to me why and how one would implement a getitem function?

For your current code, a __getitem__ isn't needed. Your class works fine (except for the undefined SelObj) when I remove the __getitem__ implementation.

The reason for the maximum recursion depth error is the definition of __getitem__, which uses self[index]: a shorthand notation for self.__getitem__(index). If you must override __getitem__, then make sure you call the superclass implementation of __getitem__:

def __getitem__(self, index):
    return super(Darray, self).__getitem__(index)

As for why you'd do this: there are lots of reasons for overriding this function, e.g. you might associate names with the rows of an array:

class NamedRows(np.ndarray):
    def __new__(cls, rows, *args, **kwargs):
        obj = np.asarray(*args, **kwargs).view(cls)
        obj.__row_name_idx = dict((n, i) for i, n in enumerate(rows))
        return obj

    def __getitem__(self, idx):
        if isinstance(idx, basestring):
            idx = self.__row_name_idx[idx]
        return super(NamedRows, self).__getitem__(idx)

Demo:

>>> a = NamedRows(["foo", "bar"], [[1,2,3], [4,5,6]])
>>> a["foo"]
NamedRows([1, 2, 3])
like image 176
Fred Foo Avatar answered Oct 13 '22 00:10

Fred Foo


The problem is here:

def __getitem__(self, index):        
    return self[index]

foo[index] just calls foo.__getitem__(index). But in your case, that just returns foo[index], which just calls foo.__getitem__(index). Which repeats in an infinite loop until you run out of stack space.

If you want to defer to your parent class, you have to do this:

def __getitem__(self, index):        
    return super(Darray, self)[index]

… or, maybe more explicitly:

def __getitem__(self, index):        
    return super(Darray, self).__getitem__(index)
like image 28
abarnert Avatar answered Oct 12 '22 23:10

abarnert