cython:如何创建cdef类的数组

cython:如何创建cdef类的数组,cython,Cython,我想要一个cdef类的cython数组: cdef class Child: cdef int i def do(self): self.i += 1 cdef class Mother: cdef Child[:] array_of_child def __init__(self): for i in range(100): self.array_of_child[i] = Child() 答案是否

我想要一个cdef类的cython数组:

cdef class Child:
    cdef int i

    def do(self):
        self.i += 1

cdef class Mother:
    cdef Child[:] array_of_child

    def __init__(self):
        for i in range(100):
            self.array_of_child[i] = Child()

答案是否定的——这实际上不可能以一种有用的方式实现:

不可能有一个
Child
s的直接数组(在单个块中分配)。部分原因是,如果在其他地方获得了对数组中
子项的引用,则该
子项
必须保持活动状态(而不是整个数组),这将无法确保它们是否都分配在同一内存块中。此外,如果要调整数组的大小(如果这是一项要求),那么它将使对数组中对象的任何其他引用无效

因此,只剩下一组指向
子对象的指针。这样的结构很好,但内部看起来几乎完全像Python列表(因此在Cython中执行更复杂的操作毫无益处…)

有几个合理的解决办法:

  • 新闻组文章中建议的解决方法只是使用python列表。您还可以将numpy数组与
    dtype=object
    一起使用。如果需要访问类中的cdef函数,可以先执行强制转换:

    cdef Child c = <Child?>a[0] # omit the ? if you don't want
                                # the overhead of checking the type.
    c.some_cdef_function()
    
    就数据结构而言,这是一个指针数组(即与Python列表相同,但可以是多维的)。它避免了
    铸造的需要。它不做的重要事情是任何类型的检查-如果你将一个不是
    子对象的对象输入数组,那么它不会注意到(因为底层
    dtype
    object
    ),但会给出无意义的答案或分段错误

    在我看来,这种方法在两件事上给了你一种错误的安全感:首先,你已经建立了一个更高效的数据结构(你没有,它基本上与列表相同);第二,你有任何类型的安全。然而,它确实存在。(如果要使用memoryview,例如,对于多维数组,可能最好使用类型为
    object
    的memoryview-这是对底层数据类型的诚实描述)


  • 你有什么理由相信我的答案过时了吗?我看了一下变更日志,没有看到任何明显的变化。我认为这不太可能改变有很好的技术原因。你所说的“cdef类的cython数组”是什么意思?对于某些
    n
    Child*
    ,它是否对应于c++的
    Child a[n]
    ?显然,您的代码中存在一些问题(应该是
    self.array\u of_child
    ,应该为
    array\u of_child
    分配内存,然后释放),因此解决这些问题可能会使您的目标更加清晰。
    array_of_child = np.array([(Child() for i in range(100)])