.. _array-array: ========================== Working with Python arrays ========================== Python has a builtin array module supporting dynamic 1-dimensional arrays of primitive types. It is possible to access the underlying C array of a Python array from within Cython. At the same time they are ordinary Python objects which can be stored in lists and serialized between processes when using :obj:`multiprocessing`. Compared to the manual approach with :c:func:`malloc` and :c:func:`free`, this gives the safe and automatic memory management of Python, and compared to a Numpy array there is no need to install a dependency, as the :obj:`array` module is built into both Python and Cython. Safe usage with memory views ---------------------------- :: from cpython cimport array as c_array from array import array cdef c_array.array a = array('i', [1, 2, 3]) cdef int[:] ca = a print ca[0] 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 `array module `_. 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 as c_array from array import array cdef c_array.array a = 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 Zero-overhead, unsafe access to raw C pointer --------------------------------------------- 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 as c_array from array import array cdef c_array.array a = 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)) Cloning, extending arrays ------------------------- 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 as c_array from array import array cdef c_array.array int_array_template = array('i', []) cdef c_array.array newarray # create an array with 3 elements with same type as template newarray = c_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 as c_array from array import array cdef c_array.array a = array('i', [1, 2, 3]) cdef c_array.array b = array('i', [4, 5, 6]) # extend a with b, resize as needed c_array.extend(a, b) # resize a, leaving just original three elements c_array.resize(a, len(a) - len(b))