Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why is cpdef not used with __init__ in cython

Tags:

cython

Had a basic question after reading the Cython documentation on classes, but I thought to get it clear. Here is a sample code from the Cython documentation:

cdef class Rectangle:
    cdef int x0, y0
    cdef int x1, y1
    def __init__(self, int x0, int y0, int x1, int y1):
        self.x0 = x0; self.y0 = y0; self.x1 = x1; self.y1 = y1
    cpdef int area(self):
        cdef int area
        area = (self.x1 - self.x0) * (self.y1 - self.y0)
        if area < 0:
            area = -area
        return area

Why is the __init__ preceded by def and not cdef or cpdef?

I realize that there is a __cinit__ function, but shouldn't making cpdef __init__ make the __init__ code faster?

Or, are we supposed to put the code, that we need to make very fast, in the __cinit__ section and the code, which we can afford to run slower, in the __init__ section?

like image 538
uday Avatar asked Nov 09 '22 08:11

uday


1 Answers

cpdef does not affect the speed of the code inside the function. It only creates a version of the function that can be called directly from C/Cython (without having to go through the Python call mechanism). The "inside" of the function is compiled in both cases and runs at exactly the same speed. See Definition of def, cdef and cpdef in cython for a full discussion.

Most Cython special functions (those with names of the form __xxx__) are restricted to being defined as def functions. Essentially because they serve a special purpose to the Python interpreter and Cython won't be able to use the C shortcut version. __init__ is no exception - it's part of the normal Python construction mechanism and so it only make senses to call it as a Python method.

__cinit__ is a slightly odd case - it can only be invoked by the Cython (implicitly) and cannot be called by the user. It therefore isn't really either a normal def, cdef or cpdef method. It's therefore just a matter of language design what keyword is used to define it (whatever you chose, it'd always be called in the same way anyway). In terms of what arguments it accepts it behaves like a def function though since it can handle *args and **kwds but only types that can be directly converted from Python objects (i.e. not C pointers).


If you can to make an alternate cdef (or cpdef) staticmethod constructor to be called directly from Cython you can. This is discussed in the documentation.

like image 56
DavidW Avatar answered Jan 04 '23 03:01

DavidW