Magic methods in extension types

Jacek Generowicz jacek.generowicz at cern.ch
Mon Apr 26 11:00:13 EDT 2004


Michael Hudson <mwh at python.net> writes:

> Jacek Generowicz <jacek.generowicz at cern.ch> writes:
> 
> > Michael Hudson <mwh at python.net> writes:
> > 
> > > Not finding the tp_as_number->nb_inplace_add field?
> > 
> > ( ... or tp_as_sequence ... )
> > 
> > I was afraid you (someone) was going to say that.
> 
> Why?

Because I'm too lazy to pollute my tiny extension type with a whole
thingy_as_number sturucture for the sake of just one maginc method :-)

> Well, the type of old-style classes has something in it's
> tp_as_number->nb_inplace_add slot that looks in the class dictionary
> for an __iadd__ method.
> 
> If you'd made that a new-style class, you would be surprised!

Don't follow ... you mean if I had done this:

    >>> class foo(object):
    ...     def __iadd__(self,other):
    ...         print "__iadd__ running"
    ...         return self
    ... 
    >>> f = foo()
    >>> f += 2
    __iadd__ running

?

> > Python manages to map "+=" to the method called "__iadd__" in
> > user-defined classes, but not for extension types. What is the
> > essential difference that makes that mapping work in one case but
> > not in the other?
> 
> Well, for old-style classes a whole bunch of code like:
> 
> BINARY_INPLACE(instance_ior, "or", PyNumber_InPlaceOr)
> BINARY_INPLACE(instance_ixor, "xor", PyNumber_InPlaceXor)
> BINARY_INPLACE(instance_iand, "and", PyNumber_InPlaceAnd)
> BINARY_INPLACE(instance_ilshift, "lshift", PyNumber_InPlaceLshift)
> BINARY_INPLACE(instance_irshift, "rshift", PyNumber_InPlaceRshift)
> BINARY_INPLACE(instance_iadd, "add", PyNumber_InPlaceAdd)
> BINARY_INPLACE(instance_isub, "sub", PyNumber_InPlaceSubtract)
> BINARY_INPLACE(instance_imul, "mul", PyNumber_InPlaceMultiply)
> BINARY_INPLACE(instance_idiv, "div", PyNumber_InPlaceDivide)
> BINARY_INPLACE(instance_imod, "mod", PyNumber_InPlaceRemainder)
> BINARY_INPLACE(instance_ifloordiv, "floordiv", PyNumber_InPlaceFloorDivide)
> BINARY_INPLACE(instance_itruediv, "truediv", PyNumber_InPlaceTrueDivide)
> 
> and for new-style classes much hair in typeobject.c:type_new and
> therein called functions.  Extension types don't go through type_new
> and are expected to go the other way round, in a sense: define
> something in tp_as_number->nb_inplace_add and a wrapper called
> __iadd__ will be created for you.

Yuk.

You are, in summary, saying that by _far_ the simplest way of adding
__iadd__ to an extenion type is via tp_as_number->nb_inplace_add,
aren't you.

So be it.

Thanks.



More information about the Python-list mailing list