5

For sake of simplicity I've defined a class that is not subclassed from ndarray (for many reasons I find it very complicated), but has an __array__() method that returns a nd.array of a given fixed shape. Let's call this class Foo.

In my script I also generate large lists of Foo instances, and I want to convert them into numpy arrays of arrays. I can easily do it using a map function:

numpy.array(map(lambda x: numpy.array(x), [foo_1, ..., foo_n]))

and it works fine. I was just wondering how I can get things ever more simpler and efficient, and get the following to work:

numpy.array([foo_1, ..., foo_n])

(actually it returns an "error return without exception set"...). It seems that providing an __array__ method is not sufficient to authorize array conversion of lists. Any idea?

2
  • can you include a minimal definition of Foo? is Foo iterable? Other than that, you should re-consider subclassing ndarray... Commented Aug 21, 2014 at 21:09
  • Foo is quite long. The key point is that is has a private attribute which is a 3x3 ndarray. I want Foo instances to behave like this private attribute in some cases, like the above one. Commented Aug 22, 2014 at 6:58

2 Answers 2

3

From the numpy.array docs, the object you pass in must satisfy:

An array, any object exposing the array interface, an object whose __array__ method returns an array, or any (nested) sequence.

You're actually passing in a list of foo objects, so this list doesn't expose the array interface and doesn't have an array method. That leaves only whether it's a nested sequence. To be a nested sequence, your foo objects would likely need to be iterable. Are they? (emulating python's container types)

Not sure if this is any better, but you could probably do:

numpy.array([numpy.array(x) for x in [foo_1, ..., foo_n]])

Here is an example of Foo, as you've described. It outputs the ndarray you'd expect (no exceptions). Hopefully you can use it as an example:

import numpy as np

class Foo(object):
    def __init__(self):
        self.arr = np.array([[1, 2, 3], [4, 5, 6], [7,8,9]], np.int32)

    def __array__(self):
        return self.arr

    def __iter__(self):
        for elem in self.arr:
            yield elem

    def __len__(self):
        return len(self.arr)

    def __getitem__(self, key):
        return self.arr[key]

def main():
    foos = [Foo() for i in range(10)]
    print np.array(foos)


if __name__ == '__main__':
    main()
Sign up to request clarification or add additional context in comments.

3 Comments

Tried to emulate iterable by defining the following methods to Foo: 'iter', 'getitem', 'len','contains', 'add', 'mul','rmul', 'radd', 'contains' methods. They are simply copied from the private attribute which is a 3x3 ndarray. But this did not work either.
@Ssbd78: Not sure if your comment just got name-mangled or not, but did you try the underscore varieties? eg. _____iter_____
@Gerrat: fine! Did not work at first for me because I was too lazy and tried something like: self.__array__ = self.arr.__array__ and so on (taking your example).
0

This will be a bit more efficient and more concise, you don't need the lambda with map:

numpy.array(map(numpy.array,[foo_1, ..., foo_n]))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.