Accessing __slots__ from C

Chris ceball at users.sourceforge.net
Wed Sep 10 10:41:49 EDT 2008


Hi,

I'd like to be able to access an attribute of a particular Python
object as fast as possible from some C code.

I wondered if using __slots__ to store the attribute would allow me to
do this in a faster way.

The reason I'd like to do this is because I need to access the
attribute inside a loop within some C code, and I find that the
attribute lookup using the 'PyObject_GetAttrString' call is far slower
than any of the subsequent calculations I perform in C.

Using the 'PyObject_GetAttrString' function to get the attribute, I
find it is slightly faster when the attribute is a slot than when it
isn't, but that the attribute lookup remains the performance-limiting
factor.

Additionally, if I instead build a list of the attributes first and
pass that to the C code, using the 'PyList_GetItem' function to access
each item, the performance improves significantly. I'd rather be able
to access the information from C, instead of building the list
externally.

As far as I can tell, nothing is documented about accessing __slot__
members in a special way from C, but perhaps someone knows how to do
it anyway?

To be more specific, below is an example of what I'm talking about. I
use SciPy's weave to inline C code, but I assume that doesn't make any
difference to my problem.

Thanks for any suggestions,
Chris



class MyObject(object):

   __slots__ = ['attr_one']

   def __init__(self,attr_one=1.0):
       self.attr_one = attr_one


import weave
def test_loop(myobjects):

   rows,cols = len(myobjects),len(myobjects[0])

   code = """
   for (int r=0; r<rows; ++r) {
       PyObject *myobjects_row = PyList_GetItem(myobjects,r);
       for (int l=0; l<cols; ++l) {
           PyObject *myobject = PyList_GetItem(myobjects_row,l);
           // any faster way when attr_one is a slot?
           PyObject *attr_one_obj=PyObject_GetAttrString(myobject,"attr_one");

           // more computations involving attr_one; just print for now...
           double attr_one = PyFloat_AsDouble(attr_one_obj);
           printf("%f\\n",attr_one);
           }
       }
   """
   weave.inline(code,['myobjects','rows','cols'],local_dict=locals(),verbose=1)


test_list = [[MyObject(0.0),MyObject(1.0)],[MyObject(2.0),MyObject(3.0)]]

test_loop(test_list)





More information about the Python-list mailing list