2011-01-28 9 views
7

Tôi cần phải có một mảng các đối tượng python được sử dụng trong việc tạo cơ sở hạ tầng trie. Tôi cần một cấu trúc sẽ được cố định chiều dài giống như một tuple và có thể thay đổi giống như một danh sách. Tôi không muốn sử dụng danh sách vì tôi muốn có thể đảm bảo rằng danh sách là chính xác kích thước phù hợp (nếu nó bắt đầu phân bổ các phần tử phụ, chi phí bộ nhớ có thể tăng lên rất nhanh khi trie phát triển lớn hơn). Có cách nào để làm việc này không? Tôi đã cố gắng tạo ra một mảng của các đối tượng:Làm cách nào để tạo một mảng có thể thay đổi, có thể thay đổi được của các đối tượng Python trong Cython?

cdef class TrieNode: 
    cdef object members[32] 

... nhưng điều đó đã đưa ra một lỗi:

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 

cách tốt nhất để làm những gì tôi đang cố gắng để làm là gì?

Trả lời

0

Làm thế nào về điều này?

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

Tùy chọn của tôi là 'khẳng định 0 <= idx

+1

Xin lỗi, nhưng đây không phải là ngay cả trong các ballpark bên phải của những gì tôi đang tìm kiếm. Hai điều: 1) Tôi đã tìm kiếm một cách để làm điều này trong cython để tạo ra một phần mở rộng C. 2) Tôi không có cách nào để buộc danh sách phải lấy chính xác 32 phần tử. Nó có một 'len' của 32, nhưng thường có nhiều không gian hơn được phân bổ để làm cho việc phụ thêm dễ dàng hơn. –

1

Nếu bạn chỉ cần vài kích thước cố định của một cấu trúc như vậy, tôi muốn nhìn vào làm cho các lớp học với thống nhất đặt tên __slots__, trong đó có một size khe để lưu trữ kích thước. Bạn sẽ cần phải khai báo một lớp riêng biệt cho mỗi kích thước (số khe). Xác định hàm cdecl để truy cập các vị trí theo chỉ mục. Hiệu năng truy cập có thể sẽ không tuyệt vời như với các địa chỉ đơn giản của một mảng C, nhưng bạn sẽ chắc chắn rằng chỉ có quá nhiều vị trí và không còn nữa.

4

Tôi không biết về các giải pháp tốt nhất , nhưng đây là một giải pháp :

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 

Một Cython object là một tự động refcounted PyObject *. Bạn luôn có thể cuộn các mảng của riêng mình PyObject * miễn là bạn chịu trách nhiệm đối với việc đếm ngược các trình gỡ lỗi nhỏ. Điều này có thể là một nhức đầu lớn cho các trường hợp không tầm thường.