#オブジェクトが変更可能かどうか
Pythonのリスト、numpy配列において
a = a + b
a += b
(累算代入と呼ばれる)
の挙動が違うことに注意する必要がある。
Pythonの累算代入では、可能ならばインプレース (in-place) 演算を行う。
すなわち、オブジェクトの内容が変更可能ならば、新たなオブジェクトを生成しない。
そのため、オブジェクトが変更可能(mutable)か変更不能(immutable)かが重要になってくる。数値型は変更不能なオブジェクトで、リストは変更可能なオブジェクトである。
#id関数で実験
Pythonの組み込み関数にid関数というものがある。
id関数を使うことで、オブジェクトの識別値を取得できる。識別値はオブジェクトの有効期間中は一意かつ定数であることが保証されている。
なので、このid関数を使って両者の違い説明をする。
#数値型
まずはa+=1
から。
a = 1
print (id(a))
a += 1
print (id(a))
1663828464
1663828496
aの識別値が変わっていることがわかる。
Pythonでは数値型は変更不能(immutable)なオブジェクトであり、
a+=1
の処理によってaの参照先が変わるためだ。
次にa=a+1
を見てみる。
a = 1
print (id(a))
a = a + 1
print (id(a))
1656226288
1656226320
やはり、aの識別値が変わっていることがわかる。
ここまでは問題ないだろう。
#リスト
こちらが本題。
a = [0,1,2]
b = [2,3,4]
print (id(a))
a = a + b
print (id(a))
53560776
53560200
aの識別値が変わっている。
次に、
a = [0,1,2]
b = [2,3,4]
print (id(a))
a += b
print (id(a))
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
のような記述が等価とは限らないので注意が必要である。