Magic methods in extension types

Michael Hudson mwh at python.net
Mon Apr 26 08:37:04 EDT 2004


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?

> > I think *all* magic methods correspond to slots in (or near) the type
> > object -- it's practically the definition of "magic method"!
> 
> Hmmm
> 
>     >>> class foo:
>     ...     def __iadd__(self,other):
>     ...         print "__iadd__ running"
>     ...         return self
>     ... 
>     >>> f = foo()
>     >>> f += 2
>     __iadd__ running
> 
> I'd be surprised if I've added __iadd__ to a type object here, yet it
> seems to work.

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!

> 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.

Cheers,
mwh

-- 
  Windows installation day one.  Getting rid of the old windows 
  was easy - they fell apart quite happily, and certainly wont 
  be re-installable anywhere else.   -- http://www.linux.org.uk/diary/
                                       (not *that* sort of windows...)



More information about the Python-list mailing list