On Thu, May 30, 2013 at 4:27 PM, Robert Kern <robert.k...@gmail.com> wrote:
> On Thu, May 30, 2013 at 9:21 PM, Aldcroft, Thomas > <aldcr...@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@scipy.org > http://mail.scipy.org/mailman/listinfo/numpy-discussion >
_______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion