Python 有内置支持原语类型的动态 1 维数组的数组模块。从 Cython 中访问 Python 数组的底层 C 数组是可能的。同时,它们是普通 Python 对象,可以被存储在列表中并在进程之间被序列化当使用
multiprocessing
.
相比手动方式
malloc()
and
free()
,这给予 Python 安全且自动的内存管理,相比 Numpy 数组不需要安装依赖,因为
array
模块被内置在 Python 和 Cython 中。
from cpython cimport array import array cdef array.array a = array.array('i', [1, 2, 3]) cdef int[:] ca = a print(ca[0])
NB: the import brings the regular Python array object into the namespace while the cimport adds functions accessible from Cython.
A Python array is constructed with a type signature and sequence of initial values. For the possible type signatures, refer to the Python documentation for the 数组模块 .
Notice that when a Python array is assigned to a variable typed as memory view, there will be a slight overhead to construct the memory view. However, from that point on the variable can be passed to other functions without overhead, so long as it is typed:
from cpython cimport array import array cdef array.array a = array.array('i', [1, 2, 3]) cdef int[:] ca = a cdef int overhead(object a): cdef int[:] ca = a return ca[0] cdef int no_overhead(int[:] ca): return ca[0] print(overhead(a)) # new memory view will be constructed, overhead print(no_overhead(ca)) # ca is already a memory view, so no overhead
To avoid any overhead and to be able to pass a C pointer to other functions, it is possible to access the underlying contiguous array as a pointer. There is no type or bounds checking, so be careful to use the right type and signedness.
from cpython cimport array import array cdef array.array a = array.array('i', [1, 2, 3]) # access underlying pointer: print(a.data.as_ints[0]) from libc.string cimport memset memset(a.data.as_voidptr, 0, len(a) * sizeof(int))
Note that any length-changing operation on the array object may invalidate the pointer.
To avoid having to use the array constructor from the Python module, it is possible to create a new array with the same type as a template, and preallocate a given number of elements. The array is initialized to zero when requested.
from cpython cimport array import array cdef array.array int_array_template = array.array('i', []) cdef array.array newarray # create an array with 3 elements with same type as template newarray = array.clone(int_array_template, 3, zero=False)
An array can also be extended and resized; this avoids repeated memory reallocation which would occur if elements would be appended or removed one by one.
from cpython cimport array import array cdef array.array a = array.array('i', [1, 2, 3]) cdef array.array b = array.array('i', [4, 5, 6]) # extend a with b, resize as needed array.extend(a, b) # resize a, leaving just original three elements array.resize(a, len(a) - len(b))
data.as_voidptr data.as_chars data.as_schars data.as_uchars data.as_shorts data.as_ushorts data.as_ints data.as_uints data.as_longs data.as_ulongs data.as_longlongs # requires Python >=3 data.as_ulonglongs # requires Python >=3 data.as_floats data.as_doubles data.as_pyunicodes
Direct access to the underlying contiguous C array, with given type; e.g.,
myarray.data.as_ints
.
The following functions are available to Cython from the array module:
int resize(array self, Py_ssize_t n) except -1
Fast resize / realloc. Not suitable for repeated, small increments; resizes underlying array to exactly the requested amount.
int resize_smart(array self, Py_ssize_t n) except -1
Efficient for small increments; uses growth pattern that delivers amortized linear-time appends.
cdef inline array clone(array template, Py_ssize_t length, bint zero)
Fast creation of a new array, given a template array. Type will be same as
template
. If zero is
True
, new array will be initialized with zeroes.
cdef inline array copy(array self)
Make a copy of an array.
cdef inline int extend_buffer(array self, char* stuff, Py_ssize_t n) except -1
Efficient appending of new data of same type (e.g. of same array type)
n
: number of elements (not number of bytes!)
cdef inline int extend(array self, array other) except -1
Extend array with data from another array; types must match.
cdef inline void zero(array self)
Set all elements of array to zero.