diff options
author | Andreas van Cranenburgh <andreas@unstable.nl> | 2014-02-09 19:52:15 +0100 |
---|---|---|
committer | Andreas van Cranenburgh <andreas@unstable.nl> | 2014-02-09 19:52:15 +0100 |
commit | a01c839890e83b9d6ac2148111d0bb407c058a98 (patch) | |
tree | d899363adcbf3a07dbba26bc70637d00b048ad90 | |
parent | 3c13f28373dd29edce52f1b35072ac5f8820f568 (diff) | |
download | cython-a01c839890e83b9d6ac2148111d0bb407c058a98.tar.gz |
tutorial for Python arrays
-rw-r--r-- | docs/src/tutorial/array.rst | 104 | ||||
-rw-r--r-- | docs/src/tutorial/index.rst | 1 |
2 files changed, 105 insertions, 0 deletions
diff --git a/docs/src/tutorial/array.rst b/docs/src/tutorial/array.rst new file mode 100644 index 000000000..01a64b193 --- /dev/null +++ b/docs/src/tutorial/array.rst @@ -0,0 +1,104 @@ +============================ +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 +---------------------------- + +.. code-block:: python + + from cpython cimport array + from array import array + cdef 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 <http://docs.python.org/library/array.html>`_. + +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: + +.. code-block:: python + + from cpython cimport array + from array import array + cdef 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. + +.. code-block:: python + + from cpython cimport array + from libc.string cimport memset + from array import array + cdef array.array a = array('i', [1, 2, 3]) + + # access underlying pointer: + print a.data.as_ints[0] + 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. + +.. code-block:: python + + from cpython cimport array + from array import array + cdef array.array int_array_template = array('i', []) + cdef array.array newarray + + # create an array with 3 elements with same type as template + newarray = array.clone(int_array_template, 3, 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. + +.. code-block:: python + + from cpython cimport array + from array import array + cdef array.array a = array('i', [1, 2, 3]) + cdef array.array b = 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)) + diff --git a/docs/src/tutorial/index.rst b/docs/src/tutorial/index.rst index 4d683c696..14bc5d9ee 100644 --- a/docs/src/tutorial/index.rst +++ b/docs/src/tutorial/index.rst @@ -15,6 +15,7 @@ Tutorials memory_allocation pure numpy + array readings related_work appendix |