2011-01-28 16 views
7

Bir tray veri yapısı oluştururken kullanılacak bir dizi python nesnesine ihtiyacım var. Bir tuple gibi sabit uzunlukta olacak ve bir liste gibi değişebilen bir yapıya ihtiyacım var. Listeyi kullanmak istemiyorum çünkü listenin tam olarak doğru boyutta olmasını sağlamak istiyorum (eğer ekstra elemanlar tahsis etmeye başlarsa, bellek yükü daha büyük büyürken çok daha hızlı eklenebilir). Bunu yapmanın bir yolu var mı? Ben nesneleri dizisini oluşturma çalıştı:Cython'da sabit uzunlukta, değiştirilebilir bir dizi Python nesnesi nasıl oluşturabilirim?

cdef class TrieNode: 
    cdef object members[32] 

... ama bu bir hata verdi:

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 

benim yapmaya çalıştığım şey bu yapmanın en iyi yolu nedir?

cevap

0

Bu nasıl? Yalnızca böyle bir yapının birkaç sabit boyutları gerekiyorsa

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

Benim tercihim, 'assert 0 <= idx

+1

Üzgünüm, ama bu aradığım şeyin sağ top parkında bile değil. İki şey: 1) Bir C uzantısı oluşturmak için bunu cython'da yapmanın bir yolunu arıyordum. 2) Listeyi tam olarak 32 unsuru almaya zorlamak için hiçbir yolum yok. Bu 32 bir 'len ', ancak daha kolay ekleme yapmak için genellikle daha fazla alan ayrılmıştır. –

1

, ben düzgün __slots__ adlı sınıfları yapma boyutunu depolamak için bir size yuvası dahil bakardık. Her boyut için ayrı bir sınıf bildirmeniz gerekir (yuva sayısı). Dizine yuvalara erişmek için cdecl işlevini tanımlayın. Erişim performansı muhtemelen bir C dizisinin düz adres aritmetiği kadar büyük olmayacaktır, ancak sadece çok fazla yuva olduğundan ve daha fazla olmadığından emin olursunuz.

4

Ben iyi çözümü hakkında bilmek, ama burada bir çözüm yoktur:

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 

A Cython object otomatik PyObject * refcounted olduğunu. Küçük buggers'ların referandırılması sorumluluğunu üstlendiğiniz sürece her zaman kendi dizilerinizi PyObject * 'lerinizden geçirebilirsiniz. Bu önemsiz olmayan durumlar için önemli bir baş ağrısı olabilir.

İlgili konular