[Numpy-discussion] __getitem__ and creating an array of objects

Robert Kern robert.kern at gmail.com
Thu May 30 17:47:09 EDT 2013


On Thu, May 30, 2013 at 10:31 PM, Aldcroft, Thomas
<aldcroft at head.cfa.harvard.edu> wrote:

> Now I realize what seemed curious.  Here is a related example which shows
> that when initializing a numpy array of objects where __getitem__ and
> __len__ exist, np.array introspects the object item values for item in
> range(len(object)) and appears to replace the input object with an ndarray
> of the object values.
>
>>>> class Foo(object):
> ...     attr = 'hello'
> ...     def __getitem__(self, item):
> ...         return item
> ...     def __len__(self):
> ...         return 5
>
>>>> f = Foo()
>>>> f.attr
> 'hello'
>
>>>> x = np.array([f, f], dtype=object)
>>>> x
> array([[0, 1, 2, 3, 4],
>        [0, 1, 2, 3, 4]], dtype=object)
>>>> x[0]
> array([0, 1, 2, 3, 4], dtype=object)
>>>> type(x[0])
> <type 'numpy.ndarray'>
>>>> x[0].attr
> Traceback (most recent call last):
>   File "<ipython-input-16-7b865674a0b6>", line 1, in <module>
>     x[0].attr
> AttributeError: 'numpy.ndarray' object has no attribute 'attr'
>
> The actual objects that I passed in seem to be lost, which is not the
> behavior I expected.

By defining __len__ and __getitem__, you are making your objects look
like containers that array() should traverse down into, like a list,
rather than atomic items like a float. array() has to do a lot of
magic to determine what shape of an array you actually want. If you
have objects that look like containers but you don't want them to be
the atomic items, then you should first construct an empty object
array of the right shape, then populate it using slice assignment.

--
Robert Kern



More information about the NumPy-Discussion mailing list