[Pyrex] C versus Python access
Robert Bradshaw
robertwb at math.washington.edu
Tue Oct 30 23:45:11 CET 2007
Funny you should ask, there's a new call type in Cython that does
exactly this. Specifically, if you have
cdef class Rect:
cdef int width, height
def __init__(self, int width, int height):
self.width = width
self.height = height
cpdef int area(self):
return self.width * self.height
It will create a (python-accessible) def function that wraps the
cpdef function, but if the call is made on a Rect object, e.g.
cdef Rect my_rect = Rect(3,4)
print my_rect.area()
then the fast c method is called. The result is much cleaner code and
no messy wrapper functions with different names. On top of that it is
still overrideable, if you have a cdef subclass, override it with a
cpdef method, and if you (or someone using your code) creates a
python subclass, they can override it with a normal python method
(which won't be as fast of course, but will get called even if the
call is made from pyrex). The overhead is extremely small. This is an
extremely new functionality and needs to be better documented. (It
used to be called rdef by the way.)
Also, on a completely separate note, if you're interested in shaving
off CPU cycles, Cython also generates def methods with the METH_NOARG
and METH_O type if possible, to avoid overhead with tuple unpacking,
etc. (One still may have to do a dictionary lookup to call it.)
- Robert
On Oct 30, 2007, at 3:09 PM, David McNab wrote:
> Hi folks,
>
> I'm trying to optimise a pile of Pyrex code, mainly by using C method
> calls wherever possible - but trying to keep the more important
> methods
> accessible from Python.
>
> To give a simple and very silly example:
>
> cdef class Rect:
>
> cdef readonly int width, height
>
> def __init__(self, int width, int height):
> self.width = width
> self.height = height
>
> cdef public int _area(self):
> return self.width * self.height
>
> def area(self):
> return self._area()
>
> Here, I've defined a C method '_area', which can be called efficiently
> from Pyrex code without all the argument parsing, getattr, python
> object
> calls etc. Also, Python method 'area' is a thin wrapper around
> '_area()'
> which makes '_area()' available to Python callers.
>
> In this approach, I'm trying to get the best of both worlds - methods
> which can be called efficiently at C level, but are also wrapped and
> exposed to Python callers.
>
> Is there a better way to shave off CPU cycles?
>
> Cheers
> David
>
>
>
>
> _______________________________________________
> Pyrex mailing list
> Pyrex at lists.copyleft.no
> http://lists.copyleft.no/mailman/listinfo/pyrex
More information about the Pyrex
mailing list