【问题标题】:cython: how do you create an array of cdef classcython:你如何创建一个 cdef 类的数组
【发布时间】:2019-12-07 18:18:35
【问题描述】:

我想要一个 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 数组”是什么意思?对于某些nChild *,它是否对应于c++ 的Child a[n]?您的代码中显然存在一些问题(应该是self.array_of_child,应该分配然后释放array_of_child 的内存),所以也许修复这些问题会让您更清楚地了解您想要实现的目标。

标签: cython


【解决方案1】:

答案是否定的——实际上不可能以有用的方式:newsgroup post of essentially the same question

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

因此,您只剩下一个指向Child 的指针数组。这样的结构很好,但在内部看起来几乎完全像 Python 列表(所以在 Cython 中做更复杂的事情真的没有任何好处......)。

有一些合理的解决方法:

  1. 新闻组帖子中建议的解决方法是使用 python 列表。您还可以使用带有 dtype=object 的 numpy 数组。如果您需要访问类中的 cdef 函数,您可以先进行强制转换:

    cdef Child c = <Child?>a[0] # omit the ? if you don't want
                                # the overhead of checking the type.
    c.some_cdef_function()
    

    在内部,这两个选项都存储为 PyObject 指向您的 Child 对象的 C 数组,因此并不像您想象的那样低效。

  2. 另一种可能性是将您的数据存储为 C 结构 (cdef struct ChildStruct: ....),它可以很容易地存储为数组。当您需要该结构的 Python 接口时,您可以定义 Child 使其包含 ChildStruct 的副本(但修改不会传播回您的原始数组),或指向 ChildStruct 的指针(但您需要小心确保没有释放指向它的Child 是活动的内存)。

  3. 您可以使用 Numpy structured array - 这与使用 C 结构数组非常相似,除了 Numpy 处理内存并提供 Python 接口。

  4. 您问题中的 memoryview 语法有效:cdef Child[:] array_of_child。这可以从 dtype object 的 numpy 数组初始化:

    array_of_child = np.array([(Child() for i in range(100)])
    

    就数据结构而言,这是一个指针数组(即与 Python 列表相同,但可以是多维的)。它避免了&lt;Child&gt; 转换的需要。它不做的重要事情是 any 类型检查 - 如果你将一个不是 Child 的对象输入到数组中,那么它不会注意到(因为底层的 @987654341 @ 是 object),但会给出无意义的答案或分段错误。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多