summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas van Cranenburgh <andreas@unstable.nl>2014-02-09 19:52:15 +0100
committerAndreas van Cranenburgh <andreas@unstable.nl>2014-02-09 19:52:15 +0100
commita01c839890e83b9d6ac2148111d0bb407c058a98 (patch)
treed899363adcbf3a07dbba26bc70637d00b048ad90
parent3c13f28373dd29edce52f1b35072ac5f8820f568 (diff)
downloadcython-a01c839890e83b9d6ac2148111d0bb407c058a98.tar.gz
tutorial for Python arrays
-rw-r--r--docs/src/tutorial/array.rst104
-rw-r--r--docs/src/tutorial/index.rst1
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