2011-01-28 2 views
7

Мне нужно иметь массив объектов python, которые будут использоваться при создании структуры данных trie. Мне нужна структура, которая будет фиксированной длины как кортеж и изменена как список. Я не хочу использовать список, потому что я хочу, чтобы убедиться, что в списке точно нужного размера (если он начнет выделять дополнительные элементы, накладные расходы на память могут складываться очень быстро, так как trie становится больше). Есть ли способ сделать это? Я попытался создать массив объектов:Как создать фиксированный размер, изменяемый массив объектов Python в Cython?

cdef class TrieNode: 
    cdef object members[32] 

... но это дало ошибку:

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 

Что такое лучший способ сделать то, что я пытаюсь сделать?

ответ

0

Как насчет этого?

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

Мое предпочтение - 'assert 0 <= idx

+1

Простите, но это даже не в нужном месте, что я ищу. Две вещи: 1) Я искал способ сделать это на cython, чтобы создать расширение C. 2) У меня нет никакого способа заставить список заняться ровно 32 элементами. Он имеет len' из 32, но обычно больше места выделяется для упрощения добавления. –

1

Если вам нужно всего лишь несколько фиксированных размеров такой структуры, я хотел бы посмотреть на то, чтобы классы с равномерно по имени __slots__, в том числе один size слот для хранения размера. Вам нужно будет объявить отдельный класс для каждого размера (количество слотов). Определите функцию cdecl для доступа к слотам по индексу. Производительность доступа, вероятно, будет не такой большой, как с простой арифметикой адресов массива C, но вы будете уверены, что есть только так много слотов и не больше.

4

Я не знаю, о решении в лучше, но вот решение:

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 

Cython object является автоматически refcounted PyObject *. Вы всегда можете сворачивать свои собственные массивы PyObject *, пока вы берете на себя ответственность за пересчет маленьких искателей. Это может быть серьезной головной болью для нетривиальных случаев.

Смежные вопросы