NumPy: Make arrays immutable (read-only) with the WRITEABLE attribute
The NumPy array (numpy.ndarray
) is mutable by default, which means you can update the values of its elements. By changing the settings of numpy.ndarray
, you can make it immutable (read-only).
Making an array immutable can be useful for preventing accidental value updates.
This article covers the following topics.
- The
flags
attribute stores memory layout information ofndarray
- Make the
ndarray
immutable (read-only) with theWRITEABLE
attribute - Situations where the
WRITEABLE
attribute cannot be changed
Keep in mind that if the original array is writable, you can still update the element values from the original array even if you make its view read-only, as discussed later.
The flags
attribute stores memory layout information of ndarray
The memory layout information of numpy.ndarray
is stored in the flags
attribute.
import numpy as np
a = np.arange(3)
print(a)
# [0 1 2]
print(a.flags)
# C_CONTIGUOUS : True
# F_CONTIGUOUS : True
# OWNDATA : True
# WRITEABLE : True
# ALIGNED : True
# WRITEBACKIFCOPY : False
# UPDATEIFCOPY : False
print(type(a.flags))
# <class 'numpy.flagsobj'>
The flags
attribute returns an object of type numpy.flagsobj
. You can access its attribute values using either the .attribute_name
(lowercase) or ['ATTRIBUTE_NAME']
(uppercase) notation.
print(a.flags.writeable)
# True
print(a.flags['WRITEABLE'])
# True
Make the ndarray
immutable (read-only) with the WRITEABLE
attribute
You can make the ndarray
immutable (read-only) with the WRITEABLE
attribute.
When you create a new numpy.ndarray
, the WRITEABLE
attribute is set to True
by default, allowing you to update its values.
a[0] = 100
print(a)
# [100 1 2]
By setting the WRITEABLE
attribute to False
, the array becomes read-only, and attempting to update its values will result in an error.
a.flags.writeable = False
# a[0] = 0
# ValueError: assignment destination is read-only
You can change the WRITEABLE
attribute using either .writeable
or ['WRITEABLE']
, or you can alternatively change the setting with the setflags()
method. In setflags()
, the write
argument corresponds to the WRITEABLE
attribute.
a.flags['WRITEABLE'] = False
a.setflags(write=False)
Situations where the WRITEABLE
attribute cannot be changed
The WRITEABLE
attribute isn't always changeable.
For example, when you create a view of a numpy.ndarray
array with a slice, if the original array is read-only (WRITEABLE
is False
), the view will also be read-only.
a = np.arange(3)
print(a)
# [0 1 2]
a.flags.writeable = False
a_view = a[1:]
print(a_view)
# [1 2]
print(a_view.flags.writeable)
# False
# a_view[0] = 100
# ValueError: assignment destination is read-only
If the original array is read-only, you cannot change the WRITEABLE
attribute of the view to True
.
# a_view.flags.writeable = True
# ValueError: cannot set WRITEABLE flag to True of this array
Even if you set the WRITEABLE
attribute of the original array to True
, the WRITEABLE
attribute of the view remains False
, but it becomes changeable to True
.
a.flags.writeable = True
print(a_view.flags.writeable)
# False
a_view.flags.writeable = True
a_view[0] = 100
print(a_view)
# [100 2]
print(a)
# [ 0 100 2]
If the WRITEABLE
attribute of the original array is True
, you can update the values from the original array even when the WRITEABLE
attribute of the view is False
.
a_view.flags.writeable = False
# a_view[1] = 1
# ValueError: assignment destination is read-only
print(a.flags.writeable)
# True
a[1] = 1
print(a)
# [0 1 2]
print(a_view)
# [1 2]
In the case of a copy, a new array is created, so you can set the WRITEABLE
attribute independently of the original array.
a.flags.writeable = False
a_copy = a[1:].copy()
print(a_copy)
# [1 2]
print(a_copy.flags.writeable)
# True
a_copy[0] = 100
print(a_copy)
# [100 2]
print(a)
# [0 1 2]
To determine whether an ndarray
is a view or a copy and if it shares memory, refer to the following article: