[Python-Dev] Using descriptors to dynamically attach methods written in Python to C-defined (new-style) types

Bob Ippolito bob at redivi.com
Sat Mar 26 01:39:46 CET 2005

On Mar 25, 2005, at 6:13 PM, Travis Oliphant wrote:

> In updating Numeric to take advantage of the new features in Python, 
> I've come across the need
> to attach a Python-written function as a method to a C-builtin.  I 
> don't want to inherit, I just want to extend the methods of a builtin 
> type using a Python function.   I was thinking of updating the new 
> type objects dictionary with a new entry that is a descriptor object.

You probably do want to inherit at least once from Python, see below.

> It seems that the descriptor mechanism makes this a relatively 
> straightforward thing.  My question is, can I use the 
> already-available Descriptor objects to do this, or will I need to 
> define another Descriptor object.  (Perhaps a PythonMethod descriptor 
> object to complement the Method Descriptor).
> Any hints will be helpful.

If the type object does have a mutable dictionary (not a read-only 
dictproxy), you're pretty much already done.  Functions implement the 
descriptor protocol, presumably even in the way you want them to.  
Meaning, if you just stick a function into a (new style) class dict, 
when you fetch it from an instance you'll end up with a bound method.  
When you fetch it from the class, you end up with an unbound method.  
There's no noticeable difference between if you did this, or if the 
class had the function when it was defined.  Functions (aka methods) 
defined in a class body are *nothing special*.

However, by default, extension types don't have a dict and the easiest 
way to get one is just to subclass it from Python.  So, what you can do 
is simply not make the C types part of the public API, use subclasses 
of them as the API for the classes that you need/want to be extensible 
in this manner.  This is the reason you can't do "object.foo = 1" but 
you CAN do it to any Python subclass of object (unless you explicitly 
disallow it by way of metaclass or slots).


More information about the Python-Dev mailing list