sometype.__new__ and C subclasses

Carl Banks pavlovevidence at gmail.com
Sun May 2 17:39:27 EDT 2010


On May 2, 1:51 pm, Robert Kern <robert.k... at gmail.com> wrote:
> On 2010-05-02 15:28 , Carl Banks wrote:
>
>
>
> > On May 2, 10:48 am, James Porter<port... at alum.rit.edu>  wrote:
> >> On 5/2/2010 4:34 AM, Carl Banks wrote:
>
> >>> Why don't you use mysubtype.__new__(mysubtype,...)?
>
> >>> If you wrote mysubtype in C, and defined a different tp_new than
> >>> ndarray, then this exception will trigger.  And it ought to; you don't
> >>> want to use ndarray's tp_new to create an object of your subclass, if
> >>> you've defined a different tp_new.
>
> >> Unfortunately, I can't do that, since that call is in NumPy itself and
> >> it's part of their "standard" way of making instances of subclasses of
> >> ndarray. Functions like numpy.zeros_like use ndarray.__new__(subtype,
> >> ...) to create new arrays based on the shape of other arrays.
>
> >> The Python version of the subclass is shown here:
> >> <http://docs.scipy.org/doc/numpy/user/basics.subclassing.html#slightly...>,
> >> and I'm trying to write something pretty similar in C. I'm trying to
> >> stay in C since everything else is in C, so it's easier to stay in C
> >> then to jump back and forth all the time.
>
> >> Maybe the real answer to this question is "NumPy is doing it wrong" and
> >> I should be on their list; still, it seems strange that the behavior is
> >> different between Python and C.
>
> > I would say numpy is wrong here, so I suggest filing a bug report.
>
> > In fact I can't think of any benefit to EVER calling X.__new__(Y)
> > where X is not Y.  Maybe old-style classes?  Someone who wants to
> > ensure they're getting an instance of a certain type can check
> > issubclass(Y,X) then call Y.__new__(Y).
>
> Well, the Y.__new__(Y) may call X.__new__(Y) (and we certainly do this
> successfully in other Python subclasses of ndarray; this also appears in the
> Python regression tests). I'm not sure why this would be permitted there and not
> in a regular function (numpy.zeros_like() seems to be the function that does
> this and fails for the OP). The reason we do it there instead of calling the
> subclass's constructor is because the subclass's constructor may have different
> arguments.
>
> I'm happy to concede that this might be a bug in numpy, but I don't understand
> why this is allowed for Python subclasses but not C subtypes.

Because Python subclasses (i.e., "heap types") all invoke
tp_new_wrapper, which is guaranteed to call the tp_new of the most
derived base.

C subtypes can, and often have to, replace tp_new with their own
version.  Calling a base type's tp_new when you've defined your own
tp_new at the C level is dangerous.


As for the issue with a subclass's arguments being different, I'm
shocked that anyone at numpy could possibly think bypassing the
subtype's constructor is good idea.


Carl Banks



More information about the Python-list mailing list