How do I create a fixed-length, mutable array of Python objects in Cython? How do I create a fixed-length, mutable array of Python objects in Cython? arrays arrays

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)