I was reading this question, about immutable numpy arrays, and in a comment to one of the answers someone shows that the given trick does not work when y = x[:]
is used rather than y = x
.
>>> import numpy as np
>>> x = np.array([1])
>>> y = x
>>> x.flags.writeable = False
>>> y[0] = 5
Traceback (most recent call last):
File "<pyshell#42>", line 1, in <module>
y[0] = 5
ValueError: assignment destination is read-only
>>> del x, y
>>> x = np.array([1])
>>> y = x[:]
>>> x.flags.writeable = False
>>> y[0] = 5
>>> x
array([5])
(Python 3.7.2, numpy 1.16.2)
What even is the difference between these two and why do they behave so differently in this specific case?
EDIT: this does not answer my question because it only asks about the situation using lists, I want to know why the numpy ndarray shows this peculiar behavior where depending on the method of copying modifying the data sometimes does and sometimes doesn't raise an error.
numpy. array is just a convenience function to create an ndarray ; it is not a class itself. You can also create an array using numpy. ndarray , but it is not the recommended way.
ndarray. An array object represents a multidimensional, homogeneous array of fixed-size items. An associated data-type object describes the format of each element in the array (its byte-order, how many bytes it occupies in memory, whether it is an integer, a floating point number, or something else, etc.)
Series can also be passed into most NumPy methods expecting an ndarray. A key difference between Series and ndarray is that operations between Series automatically align the data based on label. Thus, you can write computations without giving consideration to whether the Series involved have the same labels.
A numpy array is a grid of values, all of the same type, and is indexed by a tuple of nonnegative integers. The number of dimensions is the rank of the array; the shape of an array is a tuple of integers giving the size of the array along each dimension. The Python core library provided Lists.
y = x
just adds another reference to the existing object, no copying here. This is only adding another name for the same object into the local namespace, so it will behave in every way the same as x
.
y = x[:]
creates a shallow copy of the numpy array. This is a new Python object, but the underlying array data in memory will be the same. However, the flags are now independent:
>>> x = np.array([1])
>>> y = x[:]
>>> x.flags.owndata, y.flags.owndata
(True, False)
The owndata
flag shows that y
is just a view into the data of x
. Setting the writeable flag on x
will not change y
's flags, so y
still holds a writeable view into the data of x
.
>>> x.flags.writeable, y.flags.writeable
(True, True)
>>> x.flags.writeable = False
>>> x.flags.writeable, y.flags.writeable
(False, True)
Note that if you turn off the writeable
flag before copying x
, then the copy will also have the writeable flag unset, and you will have a read-only shallow copy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With