-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
pure
Cython provides language constructs to let the same file be either interpreted or compiled. This is accomplished by the same "magic" module cython
that directives use and which must be imported. This is available for both .py
and .pyx
files.
This is accomplished via special functions and decorators and an (optional) augmenting .pxd
file.
The currently supported attributes of the cython
module are:
- declare declares a typed variable in the current scope, which can be used in place of the
cdef type var [= value]
construct. This has two forms, the first as an assignment (useful as it creates a declaration in interpreted mode as well)x = cython.declare(cython.int) # cdef int x y = cython.declare(cython.double, 0.57721) # cdef double y = 0.57721
and the second mode as a simple function call
cython.declare(x=cython.int, y=cython.double) # cdef int x; cdef double y
- locals is a decorator that is used to specify the types of local variables in the function body (including any or all of the argument types)
@cython.locals(a=cython.double, b=cython.double, n=cython.p_double) def foo(a, b, x, y): ...
- address is used in place of the
&
operatorcython.declare(x=cython.int, x_ptr=cython.p_int) x_ptr = cython.address(x)
- sizeof emulates the
sizeof
operator. It can take both types and expressions.cython.declare(n=cython.longlong) print cython.sizeof(cython.longlong), cython.sizeof(n)
- struct can be used to create struct types.
MyStruct = cython.struct(x=cython.int, y=cython.int, data=cython.double) a = cython.declare(MyStruct)
is equivalent to the code
cdef struct MyStruct: int x int y double data cdef MyStruct a
struct construction and assignment can write as
a = MyStruct(x=5, y=6, data=2.5)
and note that one should not write
a = MyStruct(5, 6, 2.5)
since the field names are stored unordered in pure Python. (Though it works in Cython.)
- union creates union types with exactly the same syntax as
struct
- typedef creates a new type
T = cython.typedef(cython.p_int) # ctypedef int* T
- compiled is a special variable which is set to
True
when the compiler runs, andFalse
in the interpreter. Thus the codeif cython.compiled: print "Yep, I'm compiled." else: print "Just a lowly interpreted script."
will behave differently depending on whether or not the code is loaded as a compiled .so
file or a plain .py
file.
If a .pxd
file is found with the same name as a .py
file, it will be searched for cdef
classes and cdef/cpdef
functions and methods. It will then convert the corresponding classes/functions/methods in the .py
file to be of the correct type. Thus if one had a.pxd
cdef class A: cpdef foo(self, int i)
the file a.py
class A: def foo(self, i): print "Big" if i > 1000 else "Small"
would be interpreted as
cdef class A: cpdef foo(self, int i): print "Big" if i > 1000 else "Small"
The special cython
module can also be imported and used within the augmenting .pxd file. This makes it possible to add types to a pure python file without changing the file itself. For example, the following python file dostuff.py
:
def dostuff(n): t = 0 for i in range(n): t += i return t
could be augmented with the following .pxd file dostuff.pxd
import cython @cython.locals(t = cython.int, i = cython.int) cpdef int dostuff(int n)
Besides the cython.locals
decorator, the cython.declare()
function can also be used to add types to global variables in the augmenting .pxd file.
Note that normal Python (def
) functions cannot be declared in .pxd files, so it is currently impossible to override the types of Python functions in .pxd files if they use *args
or **kwargs
in their signature, for instance.
There are numerous types builtin to the cython
module. One has all the standard c types, namely
char, short, int, long, longlong
as well as their unsigned versions uchar, ushort, uint, ulong, ulonglong
.
One also has bint
and Py_ssize_t
. For each type, one has pointer types p_int, pp_int, ...
, up to three levels deep in interpreted mode, and infinitely deep in compiled mode. The Python types int, long
and bool
are interpreted as c int, long
and bint
respectively. Also, the python types list, dict, tuple, ...
may be used, as well as any user defined types.
Pointer types may be constructed with cython.pointer(cython.int)
, and arrays as cython.int[10]
. A limited attempt is made to emulate these more complex types, but only so much can be done from the Python language.
We have settled on @cython.cclass
for the cdef class decorators, and @cython.cfunc
and @cython.ccall
for cdef and cpdef functions (respectively). http://codespeak.net/pipermail/cython-dev/2008-November/002925.html