NumPy配列ndarrayをイミュータブル(書き換え禁止)に設定

NumPy配列numpy.ndarrayは基本的にミュータブルで要素を指定して値を更新可能。numpy.ndarrayの設定を変更することでイミュータブル(書き換え禁止, read-only)にできます。 誤って値を更新してしまうのを防ぐのに便利。 ここでは以下の内容について説明します。

ndarrayのメモリレイアウト情報を格納しているflags WRITEABLE属性で配列をイミュータブル(書き換え禁止)に設定 WRITEABLE属性を変更できない場合もあり

最後に説明するように、元の配列が書き換え可能である場合は、そのビューを書き換え禁止にしても元の配列から要素の値が更新できるので注意。

ndarrayのメモリレイアウト情報を格納しているflags

numpy.ndarrayのメモリレイアウトの情報はflagsに格納されています。

numpy.ndarray.flags — NumPy v1.15 Manual

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'>

numpy.flagsobjという独自の型だが、.属性名や['属性名']として各属性の値を確認できます。大文字小文字に注意。

print(a.flags.writeable)
# True

print(a.flags['WRITEABLE'])
# True

WRITEABLE属性で配列をイミュータブル(書き換え禁止)に設定

numpy.ndarrayが書き換え禁止かどうかの設定はWRITEABLE属性。 上の例のように新たにnumpy.ndarrayを作成した場合、WRITEABLEはTrueに設定されており、値を更新することが可能。

a[0] = 100

print(a)
# [100   1   2]

WRITEABLEをFalseとすると書き換え禁止となり、値を更新しようとするとエラーとなります。

a.flags.writeable = False

# a[0] = 0
# ValueError: assignment destination is read-only

.writeableや['WRITEABLE']で変更するほか、setflags()というメソッドでも設定値を変更できます。setflags()では引数writeがWRITEABLEに対応しています。

numpy.ndarray.setflags — NumPy v1.15 Manual

a.flags['WRITEABLE'] = False
a.setflags(write=False)

WRITEABLE属性を変更できない場合もあり

WRITEABLE属性は常に変更できるわけではないので注意。 例えば、スライスなどでnumpy.ndarray配列のビューを生成した場合、元の配列が書き換え禁止(WITEABLEがFalse)だとビューも書き換え禁止となります。

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

元の配列が書き換え禁止の場合は、ビューのWRITEABLE属性をTrueに変更して書き換え禁止を解除することもできない。

# a_view.flags.writeable = True
# ValueError: cannot set WRITEABLE flag to True of this array

元の配列のWRITEABLE属性をTrueにしてもビューのWRITEABLE属性はFalseのまま変わらないが、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]

ビューのWRITEABLE属性がFalseであっても、元の配列のWRITEABLE属性がTrueであれば元の配列からは更新可能。注意。

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]

コピーの場合は新たな配列が生成されるので元の配列とは独立してWRITEABLE属性を設定可能。

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]

シェア

関連カテゴリー

Python NumPy

Python, NumPy(OpenCV)で画像を二値化処理 NumPy配列ndarrayの次元数、形状、サイズ(全要素数)を取得 NumPy配列ndarrayを結合(concatenate, stack, blockなど) NumPyで全要素を同じ値で初期化した配列ndarrayを生成 NumPy配列ndarrayを分割(split, array_split, hsplit, vsplit, dsplit) NumPyで空の配列ndarrayを生成するemptyとempty_like NumPyのsortとargsort関数で任意の行・列を基準にソート NumPy配列ndarrayの行・列を任意の順番に並べ替え、選択(抽出) NumPy配列ndarrayとPython標準のリストを相互に変換 NumPy配列ndarrayを任意の最小値・最大値に収めるclip Python, OpenCV, Pillow(PIL)で画像サイズ(幅、高さ)を取得 NumPy配列ndarrayをバイナリファイル(npy, npz)で保存 Pythonのリストと配列とnumpy.ndarrayの違いと使い分け NumPy配列ndarrayに新たな次元を追加するnp.newaxis NumPy配列ndarrayに要素・行・列を挿入、追加するinsertの使い方

Last Updated: 6/26/2019, 10:34:03 PM