2011-01-28 10 views
7

Necesito tener una matriz de objetos de pitón para usar en la creación de una estructura de datos. Necesito una estructura que sea de longitud fija como una tupla y mutable como una lista. No quiero usar una lista porque quiero asegurarme de que la lista sea exactamente el tamaño correcto (si comienza a asignar elementos adicionales, la sobrecarga de memoria podría sumar muy rápidamente a medida que el trie crezca). ¿Hay alguna forma de hacer esto? He intentado crear una matriz de objetos:¿Cómo creo una matriz mutable de longitud fija de objetos de Python en Cython?

cdef class TrieNode: 
    cdef object members[32] 

... pero que dio un error:

Error compiling Cython file: 
------------------------------------------------------------ 
... 
cdef class TrieNode: 
    cdef object members[32] 
        ^
------------------------------------------------------------ 

/Users/jason/src/pysistence/source/pysistence/trie.pyx:2:23: Array element cannot be a Python object 

¿Cuál es la mejor manera de hacer lo que estoy tratando de hacer?

Respuesta

0

¿Qué tal esto?

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) 
+0

Mi preferencia es 'assert 0 <= idx

+1

Lo siento, pero esto ni siquiera está en el estadio correcto de lo que estoy buscando. Dos cosas: 1) Estaba buscando una forma de hacer esto en cython para crear una extensión C. 2) No tengo ninguna forma de forzar a la lista a tomar exactamente 32 elementos. Tiene un 'len' de 32, pero generalmente se asigna más espacio para facilitar el anexar. –

1

Si sólo necesita unos pocos tamaños fijos de una estructura de este tipo, me vería en hacer clases con uniforme llamado __slots__, incluyendo uno size ranura para almacenar el tamaño. Tendrá que declarar una clase separada para cada tamaño (cantidad de ranuras). Defina una función cdecl para acceder a las ranuras por índice. Es probable que el rendimiento de acceso no sea tan bueno como con las aritméticas de direcciones simples de una matriz C, pero estarás seguro de que solo hay tantas ranuras como ninguna otra.

4

No sé acerca de la solución mejor, pero aquí es una solución :

from cpython.ref cimport PyObject, Py_XINCREF, Py_XDECREF 

DEF SIZE = 32 

cdef 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 

Un Cython object es un refcounted automáticamente PyObject *. Siempre puede hacer rodar sus propias matrices de PyObject *, siempre que asuma la responsabilidad de volver a contar los pequeños insectores. Esto puede ser un gran dolor de cabeza para casos no triviales.

Cuestiones relacionadas