python 遍历动态分配的 Cython 数组
python iterate over dynamically allocated Cython array
我正在为 C class 编写一个 python 包装器,并且我正在使用 PyMem_Malloc 分配内存,如 here
所述
cdef class SomeMemory:
cdef double* data
def __cinit__(self, size_t number):
# allocate some memory (uninitialised, may contain arbitrary data)
self.data = <my_data_t*> PyMem_Malloc(number * sizeof(my_data_t))
if not self.data:
raise MemoryError()
然后我在另一个脚本中导入并使用 class 使用:
import SomeMemory
sm = SomeMemory(10)
我现在想访问 self.data 的元素,但我遇到了 2 个问题
- 如果我键入 self.data 并按回车键,ipython 内核会崩溃
- 如果我尝试循环自己的数据
喜欢:
for p in self.data:
print p
我收到一个错误,提示 self.data 不可迭代。
如何访问 self.data?我需要先将元素转换为 my_data_t 吗?
(根据更新的问题进行了大量编辑)
所以 - 我的理解是 self.data
需要声明为 public 才能从 Python:
访问它
cdef class SomeMemory:
cdef public double* data
# also make sure you define __dealloc__ to remove the data
但是,这里似乎没有强制执行。
但是,您真正的问题是 Python 不知道如何处理 double *
类型的对象。它肯定永远不会是可迭代的,因为关于何时停止的信息根本没有存储(所以它总是会结束。
有一系列更好的选择:
- 您将数据存储为 Python 数组(有关指南,请参阅 http://docs.cython.org/src/tutorial/array.html)。如果需要,您可以从 Cython 中快速访问原始 c 指针,而且 Python 知道如何处理它
代码如下
from cpython cimport array as c_array
from array import array
cdef class SomeMemory:
cdef c_array.array data
def __cinit__(self, size_t number):
self.data = array('d', some initial value goes here)
您将数据存储为 numpy 数组。这可能稍微复杂一些,但具有大致相同的优点。例子就不举例了,比较容易找
您使用 Cython 的类型化内存视图:http://docs.cython.org/src/userguide/memoryviews.html。这样做的好处是它可以让您自己控制内存管理(如果那对您来说 绝对 重要的话)。但是,我不是 100% 确定您可以在 Python 中干净地访问它们(懒得测试!)
您将数据包装在您自己的 class 实现 __getitem__
和 __len__
中,因此它可以用作迭代器。这可能比它值得的麻烦更多。
我推荐第一个选项,除非你有充分的理由选择其他选项。
我正在为 C class 编写一个 python 包装器,并且我正在使用 PyMem_Malloc 分配内存,如 here
所述cdef class SomeMemory:
cdef double* data
def __cinit__(self, size_t number):
# allocate some memory (uninitialised, may contain arbitrary data)
self.data = <my_data_t*> PyMem_Malloc(number * sizeof(my_data_t))
if not self.data:
raise MemoryError()
然后我在另一个脚本中导入并使用 class 使用:
import SomeMemory
sm = SomeMemory(10)
我现在想访问 self.data 的元素,但我遇到了 2 个问题
- 如果我键入 self.data 并按回车键,ipython 内核会崩溃
- 如果我尝试循环自己的数据
喜欢:
for p in self.data:
print p
我收到一个错误,提示 self.data 不可迭代。
如何访问 self.data?我需要先将元素转换为 my_data_t 吗?
(根据更新的问题进行了大量编辑)
所以 - 我的理解是 self.data
需要声明为 public 才能从 Python:
cdef class SomeMemory:
cdef public double* data
# also make sure you define __dealloc__ to remove the data
但是,这里似乎没有强制执行。
但是,您真正的问题是 Python 不知道如何处理 double *
类型的对象。它肯定永远不会是可迭代的,因为关于何时停止的信息根本没有存储(所以它总是会结束。
有一系列更好的选择:
- 您将数据存储为 Python 数组(有关指南,请参阅 http://docs.cython.org/src/tutorial/array.html)。如果需要,您可以从 Cython 中快速访问原始 c 指针,而且 Python 知道如何处理它
代码如下
from cpython cimport array as c_array
from array import array
cdef class SomeMemory:
cdef c_array.array data
def __cinit__(self, size_t number):
self.data = array('d', some initial value goes here)
您将数据存储为 numpy 数组。这可能稍微复杂一些,但具有大致相同的优点。例子就不举例了,比较容易找
您使用 Cython 的类型化内存视图:http://docs.cython.org/src/userguide/memoryviews.html。这样做的好处是它可以让您自己控制内存管理(如果那对您来说 绝对 重要的话)。但是,我不是 100% 确定您可以在 Python 中干净地访问它们(懒得测试!)
您将数据包装在您自己的 class 实现
__getitem__
和__len__
中,因此它可以用作迭代器。这可能比它值得的麻烦更多。
我推荐第一个选项,除非你有充分的理由选择其他选项。