LoginSignup
7
4

More than 5 years have passed since last update.

リスト、numpy配列の累算代入について

Posted at

オブジェクトが変更可能かどうか

Pythonのリスト、numpy配列において
a = a + b
a += b(累算代入と呼ばれる)
の挙動が違うことに注意する必要がある。

Pythonの累算代入では、可能ならばインプレース (in-place) 演算を行う。
すなわち、オブジェクトの内容が変更可能ならば、新たなオブジェクトを生成しない。

そのため、オブジェクトが変更可能(mutable)か変更不能(immutable)かが重要になってくる。数値型は変更不能なオブジェクトで、リストは変更可能なオブジェクトである。

id関数で実験

Pythonの組み込み関数にid関数というものがある。
id関数を使うことで、オブジェクトの識別値を取得できる。識別値はオブジェクトの有効期間中は一意かつ定数であることが保証されている。
なので、このid関数を使って両者の違い説明をする。

数値型

まずはa+=1から。

test1.py
a = 1
print (id(a))
a += 1
print (id(a))
test1.py実行結果
1663828464
1663828496

aの識別値が変わっていることがわかる。
Pythonでは数値型は変更不能(immutable)なオブジェクトであり、
a+=1の処理によってaの参照先が変わるためだ。
次にa=a+1を見てみる。

test2.py
a = 1
print (id(a))
a = a + 1
print (id(a))
test2.py実行結果
1656226288
1656226320

やはり、aの識別値が変わっていることがわかる。
ここまでは問題ないだろう。

リスト

こちらが本題。

test3.py
a = [0,1,2]
b = [2,3,4]
print (id(a))
a  =  a + b
print (id(a))
test3.py実行結果
53560776
53560200

aの識別値が変わっている。
次に、

test4.py
a = [0,1,2]
b = [2,3,4]
print (id(a))
a  += b
print (id(a))
test4.py実行結果
53560008
53560008

今度は、aの識別値が変わっていない。

numpy配列

くどくなってしまうので、numpy配列についての実験結果は割愛するが、
通常のリストと同様の結果になる。
numpyの公式チュートリアルにも以下のように記載がある。

Arithmetic operators on arrays apply elementwise. A new array is created and filled with the result.

Some operations, such as += and *=, act in place to modify an existing array rather than create a new one.

まとめ

a = a + b
a += b
のような記述が等価とは限らないので注意が必要である。

7
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4