summaryrefslogtreecommitdiff
path: root/doc/source/reference/arrays.nditer.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/source/reference/arrays.nditer.rst')
-rw-r--r--doc/source/reference/arrays.nditer.rst108
1 files changed, 65 insertions, 43 deletions
diff --git a/doc/source/reference/arrays.nditer.rst b/doc/source/reference/arrays.nditer.rst
index 76f5991cf..acad29b11 100644
--- a/doc/source/reference/arrays.nditer.rst
+++ b/doc/source/reference/arrays.nditer.rst
@@ -83,7 +83,14 @@ Modifying Array Values
By default, the :class:`nditer` treats the input array as a read-only
object. To modify the array elements, you must specify either read-write
-or write-only mode. This is controlled with per-operand flags.
+or write-only mode. This is controlled with per-operand flags. The
+operands may be created as views into the original data with the
+`WRITEBACKIFCOPY` flag. In this case the iterator must either
+
+- be used as a context manager, and the temporary data will be written back
+ to the original array when the `__exit__` function is called.
+- have a call to the iterator's `close` function to ensure the modified data
+ is written back to the original array.
Regular assignment in Python simply changes a reference in the local or
global variable dictionary instead of modifying an existing variable in
@@ -99,8 +106,9 @@ the ellipsis.
>>> a
array([[0, 1, 2],
[3, 4, 5]])
- >>> for x in np.nditer(a, op_flags=['readwrite']):
- ... x[...] = 2 * x
+ >>> with np.nditer(a, op_flags=['readwrite']) as it:
+ ... for x in it:
+ ... x[...] = 2 * x
...
>>> a
array([[ 0, 2, 4],
@@ -178,9 +186,10 @@ construct in order to be more readable.
0 <(0, 0)> 1 <(0, 1)> 2 <(0, 2)> 3 <(1, 0)> 4 <(1, 1)> 5 <(1, 2)>
>>> it = np.nditer(a, flags=['multi_index'], op_flags=['writeonly'])
- >>> while not it.finished:
- ... it[0] = it.multi_index[1] - it.multi_index[0]
- ... it.iternext()
+ >>> with it:
+ .... while not it.finished:
+ ... it[0] = it.multi_index[1] - it.multi_index[0]
+ ... it.iternext()
...
>>> a
array([[ 0, 1, 2],
@@ -385,10 +394,10 @@ parameter support.
.. admonition:: Example
>>> def square(a):
- ... it = np.nditer([a, None])
- ... for x, y in it:
- ... y[...] = x*x
- ... return it.operands[1]
+ ... with np.nditer([a, None]) as it:
+ ... for x, y in it:
+ ... y[...] = x*x
+ ... return it.operands[1]
...
>>> square([1,2,3])
array([1, 4, 9])
@@ -426,9 +435,10 @@ reasons.
... flags = ['external_loop', 'buffered'],
... op_flags = [['readonly'],
... ['writeonly', 'allocate', 'no_broadcast']])
- ... for x, y in it:
- ... y[...] = x*x
- ... return it.operands[1]
+ ... with it:
+ ... for x, y in it:
+ ... y[...] = x*x
+ ... return it.operands[1]
...
>>> square([1,2,3])
@@ -480,10 +490,12 @@ Everything to do with the outer product is handled by the iterator setup.
>>> b = np.arange(8).reshape(2,4)
>>> it = np.nditer([a, b, None], flags=['external_loop'],
... op_axes=[[0, -1, -1], [-1, 0, 1], None])
- >>> for x, y, z in it:
- ... z[...] = x*y
+ >>> with it:
+ ... for x, y, z in it:
+ ... z[...] = x*y
+ ... result = it.operands[2] # same as z
...
- >>> it.operands[2]
+ >>> result
array([[[ 0, 0, 0, 0],
[ 0, 0, 0, 0]],
[[ 0, 1, 2, 3],
@@ -491,6 +503,9 @@ Everything to do with the outer product is handled by the iterator setup.
[[ 0, 2, 4, 6],
[ 8, 10, 12, 14]]])
+Note that once the iterator is closed we can not access :func:`operands <nditer.operands>`
+and must use a reference created inside the context manager.
+
Reduction Iteration
-------------------
@@ -505,9 +520,10 @@ For a simple example, consider taking the sum of all elements in an array.
>>> a = np.arange(24).reshape(2,3,4)
>>> b = np.array(0)
- >>> for x, y in np.nditer([a, b], flags=['reduce_ok', 'external_loop'],
- ... op_flags=[['readonly'], ['readwrite']]):
- ... y[...] += x
+ >>> with np.nditer([a, b], flags=['reduce_ok', 'external_loop'],
+ ... op_flags=[['readonly'], ['readwrite']]) as it:
+ ... for x,y in it:
+ ... y[...] += x
...
>>> b
array(276)
@@ -525,11 +541,13 @@ sums along the last axis of `a`.
>>> it = np.nditer([a, None], flags=['reduce_ok', 'external_loop'],
... op_flags=[['readonly'], ['readwrite', 'allocate']],
... op_axes=[None, [0,1,-1]])
- >>> it.operands[1][...] = 0
- >>> for x, y in it:
- ... y[...] += x
+ >>> with it:
+ ... it.operands[1][...] = 0
+ ... for x, y in it:
+ ... y[...] += x
+ ... result = it.operands[1]
...
- >>> it.operands[1]
+ >>> result
array([[ 6, 22, 38],
[54, 70, 86]])
>>> np.sum(a, axis=2)
@@ -558,12 +576,14 @@ buffering.
... 'buffered', 'delay_bufalloc'],
... op_flags=[['readonly'], ['readwrite', 'allocate']],
... op_axes=[None, [0,1,-1]])
- >>> it.operands[1][...] = 0
- >>> it.reset()
- >>> for x, y in it:
- ... y[...] += x
+ >>> with it:
+ ... it.operands[1][...] = 0
+ ... it.reset()
+ ... for x, y in it:
+ ... y[...] += x
+ ... result = it.operands[1]
...
- >>> it.operands[1]
+ >>> result
array([[ 6, 22, 38],
[54, 70, 86]])
@@ -609,11 +629,12 @@ Here's how this looks.
... op_flags=[['readonly'], ['readwrite', 'allocate']],
... op_axes=[None, axeslist],
... op_dtypes=['float64', 'float64'])
- ... it.operands[1][...] = 0
- ... it.reset()
- ... for x, y in it:
- ... y[...] += x*x
- ... return it.operands[1]
+ ... with it:
+ ... it.operands[1][...] = 0
+ ... it.reset()
+ ... for x, y in it:
+ ... y[...] += x*x
+ ... return it.operands[1]
...
>>> a = np.arange(6).reshape(2,3)
>>> sum_squares_py(a)
@@ -661,16 +682,17 @@ Here's the listing of sum_squares.pyx::
op_flags=[['readonly'], ['readwrite', 'allocate']],
op_axes=[None, axeslist],
op_dtypes=['float64', 'float64'])
- it.operands[1][...] = 0
- it.reset()
- for xarr, yarr in it:
- x = xarr
- y = yarr
- size = x.shape[0]
- for i in range(size):
- value = x[i]
- y[i] = y[i] + value * value
- return it.operands[1]
+ with it:
+ it.operands[1][...] = 0
+ it.reset()
+ for xarr, yarr in it:
+ x = xarr
+ y = yarr
+ size = x.shape[0]
+ for i in range(size):
+ value = x[i]
+ y[i] = y[i] + value * value
+ return it.operands[1]
On this machine, building the .pyx file into a module looked like the
following, but you may have to find some Cython tutorials to tell you