How do I create a fixed-length, mutable array of Python objects in Cython?
I don't know about the best solution, but here's a solution:
from cpython.ref cimport PyObject, Py_XINCREF, Py_XDECREFDEF SIZE = 32cdef class TrieNode: cdef PyObject *members[SIZE] def __cinit__(self): cdef object temp_object for i in range(SIZE): temp_object = int(i) # increment its refcount so it's not gc'd. # We hold a reference to the object and are responsible for # decref-ing it in __dealloc__. Py_XINCREF(<PyObject*>temp_object) self.members[i] = <PyObject*>temp_object def __init__(self): # just to show that it works... for i in range(SIZE): print <object>self.members[i] def __dealloc__(self): # make sure we decref the members elements. for i in range(SIZE): Py_XDECREF(self.members[i]) self.members[i] = NULL
A Cython object
is an automatically refcounted PyObject *
. You can always roll your own arrays of PyObject *
's as long as you take responsibility for refcounting the little buggers. This can be a major headache for non-trivial cases.
If you only need few fixed sizes of such a structure, I'd look at making classes with uniformly named __slots__
, including one size
slot to store the size. You'll need to declare a separate class for each size (number of slots). Define a cdecl
function to access slots by index. Access performance will probably be not as great as with plain address arithmetics of a C array, but you'll be sure that there's only so many slots and none more.
How about this?
class TrieNode(): def __init__(self, length = 32): self.members = list() self.length = length for i in range(length): self.members.append(None) def set(self, idx, item): if idx < self.length and idx >= 0: self.members[idx] = item else: print "ERROR: Specified index out of range." # Alternately, you could raise an IndexError. def unset(self, idx): if idx < self.length and idx >= 0: self.members[idx] = None else: raise IndexError("Specified index out of range (0..%d)." % self.length)