[Numpy-discussion] Preventing an ndarray subclass from returning new subclass instances for std(), etc

Aronne Merrelli aronne.merrelli at gmail.com
Mon Sep 19 10:26:49 EDT 2011


On Sun, Sep 18, 2011 at 3:58 PM, Wes McKinney <wesmckinn at gmail.com> wrote:

>
> I thought maybe you can intercept 0-dim objects and return self.item()
> in array_finalize, but not dice. This is really weird:
>
> import numpy as np
>
> class example(np.ndarray):
>
>    def __new__(cls, arr):
>        return np.array(arr).view(cls)
>
>    def __array_finalize__(self, obj):
>         print 'foo'
>        if self.ndim == 0:
>            return self.item()
>
>
> In [6]: foo = example(np.arange(10))
> foo
>
> In [7]: foo.std()
> foo
> foo
> foo
> foo
> foo
> foo
> foo
> Out[7]: example(2.8722813232690143)
> _______________________________________________
>


The documentation on array_wrap/finalize isn't too clear on this point, but
I think the return from __array_finalize__ is actually not used in any way.
So, in this example, I think it the returned self.item() is discarded. The
only important "output" from __array_finalize__ is whatever modification was
made to the self object. The 'caller' of __array_finalize__ is (I think)
somewhere is the C code, so I can't verify this (I'm not really a C
programmer...).

The series of "foos" is due to the std calculation, if you change "print
'foo'" to "print 'foo', obj" you get this output:

In [71]: a = example([1,2,3])
foo [1 2 3]

In [72]: a.std()
foo [1 2 3]
foo 6.0
foo 2.0
foo [1 2 3]
foo [1 2 3]
foo [-1.  0.  1.]
foo [ 1.  0.  1.]
foo 2.0
foo 0.666666666667
Out[72]: example(0.816496580927726)


Anyway, back on topic - I'm having similar problems as Keith. It seems like
there isn't consistency on how different built-in functions treat
array_wrap/finalize/etc, or maybe I'm still confused. At the moment it seems
like the only solution is to write a method in the subclass for each case
where the return isn't what you want. In this example, to force the result
of std() to be an ndarray instead of the subclass, you would need to write
something similar to:

import numpy as np
class example(np.ndarray):
   def __new__(cls, arr):
       return np.array(arr).view(cls)
   def std(self, *args, **kwargs):
       return np.array(self).std(*args, **kwargs)


Is this the best way to handle this problem? It could make the subclass
definition quite cluttered, but on the other hand all these extra methods
would be pretty straightforward.


Thanks,
Aronne
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20110919/f6f24279/attachment.html>


More information about the NumPy-Discussion mailing list