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

Aldcroft, Thomas aldcroft at head.cfa.harvard.edu
Thu May 30 16:58:54 EDT 2013


On Thu, May 30, 2013 at 4:27 PM, Robert Kern <robert.kern at gmail.com> wrote:

> On Thu, May 30, 2013 at 9:21 PM, Aldcroft, Thomas
> <aldcroft at head.cfa.harvard.edu> wrote:
> > I'm seeing some behavior that I can't understand when creating a numpy
> array
> > of Python objects.  Basically it seems that np.array() is calling the
> object
> > __getitem__ method for one object class but not another class, and I
> can't
> > understand the difference.
> >
> > Here is an example, starting with a simple class where __getitem__ does
> NOT
> > get called:
> >
> >>>> class Foo(object):
> > ...     def __getitem__(self, item):
> > ...         return 1/0
> > ...     def __len__(self, item):
> > ...         return 1
> > ...
> >>>> f = Foo()
> >>>> x = np.array([f])
> >>>> x
> > array([<__main__.Foo object at 0x11a1ff10>], dtype=object)
> >
> > Now move to the complicated class (astropy.time.Time) which has a lot of
> > stuff in it (including __new__, __init__, and __len__ methods, but
> initially
> > no __getitem__), but is otherwise an ordinary class derived from object.
> > This works as expected:
> >
> >>>> from astropy.time import Time
> >>>> t = Time('2001-01-01', scale='utc')
> >>>> x = np.array([t])
> >>>> x
> > array([2001-01-01 00:00:00.000], dtype=object)
> >
> > Now inject a __getitem__ that will fail and try again:
> >
> >>>> Time.__getitem__ = lambda self, item: 1 / 0
> >>>> x = np.array([t])
> > ERROR: ZeroDivisionError: integer division or modulo by zero
> >
> > Any ideas on what is driving this difference in behavior?  BTW, the
> value of
> > item in the latter case is 0.
>
> What is len(t) in the latter case?
>

>>> len(t)
1

Prompted by this question I looked again at the Foo() definition and see
that I had copy/pasted the definition of __len__ from __getitem__ and
forgot to remove the `item` arg.  As written `len(Foo())` would fail.
 Interestingly, once `Foo.__len__` is valid and succeeds, then
`f.__getitem__` does indeed get called and `np.array([f])` fails in the
same way.

Sorry for the noise, though this is still just slightly curious to me.  I
guess internally maybe there is try/except block that is trying to get a
len and if that fails then it moves on.

- Tom



>
> --
> Robert Kern
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion at scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20130530/60dd1794/attachment.html>


More information about the NumPy-Discussion mailing list