summaryrefslogtreecommitdiff
path: root/numpy/lib
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/lib')
-rw-r--r--numpy/lib/stride_tricks.py65
-rw-r--r--numpy/lib/tests/test_stride_tricks.py17
2 files changed, 79 insertions, 3 deletions
diff --git a/numpy/lib/stride_tricks.py b/numpy/lib/stride_tricks.py
index 4c23ab355..af09fd373 100644
--- a/numpy/lib/stride_tricks.py
+++ b/numpy/lib/stride_tricks.py
@@ -35,8 +35,61 @@ def _maybe_view_as_subclass(original_array, new_array):
return new_array
-def as_strided(x, shape=None, strides=None, subok=False):
- """ Make an ndarray from the given array with the given shape and strides.
+def as_strided(x, shape=None, strides=None, subok=False, writeable=True):
+ """
+ Create a view into the array with the given shape and strides.
+
+ .. warning:: This function has to be used with extreme care, see notes.
+
+ Parameters
+ ----------
+ x : ndarray
+ Array to create a new.
+ shape : sequence of int, optional
+ The shape of the new array. Defaults to ``x.shape``.
+ strides : sequence of int, optional
+ The strides of the new array. Defaults to ``x.strides``.
+ subok : bool, optional
+ .. versionadded:: 1.10
+
+ If True, subclasses are preserved.
+ writeable : bool, optional
+ .. versionadded:: 1.12
+
+ If set to False, the returned array will always be readonly.
+ Otherwise it will be writable if the original array was. It
+ is advisable to set this to False if possible (see Notes).
+
+ Returns
+ -------
+ view : ndarray
+
+ See also
+ --------
+ broadcast_to: broadcast an array to a given shape.
+ reshape : reshape an array.
+
+ Notes
+ -----
+ ``as_strided`` creates a view into the array given the exact strides
+ and shape. This means it manipulates the internal data structure of
+ ndarray and, if done incorrectly, the array elements can point to
+ invalid memory and can corrupt results or crash your program.
+ It is advisable to always use the original ``x.strides`` when
+ calculating new strides to avoid reliance on a contiguous memory
+ layout.
+
+ Furthermore, arrays created with this function often contain self
+ overlapping memory, so that two elements are identical.
+ Vectorized write operations on such arrays will typically be
+ unpredictable. They may even give different results for small, large,
+ or transposed arrays.
+ Since writing to these arrays has to be tested and done with great
+ care, you may want to use ``writeable=False`` to avoid accidental write
+ operations.
+
+ For these reasons it is advisable to avoid ``as_strided`` when
+ possible.
"""
# first convert input to array, possibly keeping subclass
x = np.array(x, copy=False, subok=subok)
@@ -45,13 +98,19 @@ def as_strided(x, shape=None, strides=None, subok=False):
interface['shape'] = tuple(shape)
if strides is not None:
interface['strides'] = tuple(strides)
+
array = np.asarray(DummyArray(interface, base=x))
if array.dtype.fields is None and x.dtype.fields is not None:
# This should only happen if x.dtype is [('', 'Vx')]
array.dtype = x.dtype
- return _maybe_view_as_subclass(x, array)
+ view = _maybe_view_as_subclass(x, array)
+
+ if view.flags.writeable and not writeable:
+ view.flags.writeable = False
+
+ return view
def _broadcast_to(array, shape, subok, readonly):
diff --git a/numpy/lib/tests/test_stride_tricks.py b/numpy/lib/tests/test_stride_tricks.py
index 06e659002..95df135cf 100644
--- a/numpy/lib/tests/test_stride_tricks.py
+++ b/numpy/lib/tests/test_stride_tricks.py
@@ -317,6 +317,23 @@ def test_as_strided():
a_view = as_strided(a, shape=(3, 4), strides=(0, a.itemsize))
assert_equal(a.dtype, a_view.dtype)
+def as_strided_writeable():
+ arr = np.ones(10)
+ view = as_strided(arr, writeable=False)
+ assert_(not view.flags.writeable)
+
+ # Check that writeable also is fine:
+ view = as_strided(arr, writeable=True)
+ assert_(view.flags.writeable)
+ view[...] = 3
+ assert_array_equal(arr, np.full_like(arr, 3))
+
+ # Test that things do not break down for readonly:
+ arr.flags.writeable = False
+ view = as_strided(arr, writeable=False)
+ view = as_strided(arr, writeable=True)
+ assert_(not view.flags.writeable)
+
class VerySimpleSubClass(np.ndarray):
def __new__(cls, *args, **kwargs):