Python の mutable immutableって?
Pythonオブジェクトが持っている性質のことです。
例えば、
リスト型はmutable、数値型はimmutable。
Question: なんでそんなこと知らないとダメなん?
Ans: いや、これを抑えとかないとバグで苦しむことになるんだ。
具体的には...
関数内で変数を変更したらもとの変数の値までかわちゃった! なんてことが起ります。
だから、抑えておこう。
まずは大雑把に解説
mutableとは
macの辞書で検索すると...
「変わりやすい」、「移り気の」って出てきます。
mutableなオブジェクトとは、変更可能なオブジェクトをさす言葉です。
mutableなオブジェクトの例
リスト型、辞書型、クラスなど。
リスト型はmutable
numbers = [1,2,3,4]
numbers.append(5)
print( "numbers = ", numbers )
# 出力結果 >> numbers = [1, 2, 3, 4, 5]
辞書型はmutable
pokemon = {
"ピカチュウ": "電気",
"イーブイ": "ノーマル",
"コイキング": "ドラゴン"
}
pokemon.pop("コイキング")
# 出力結果 >> pokemon = {'ピカチュウ': '電気', 'イーブイ': 'ノーマル'}
immutableとは
「im」がmuttableの頭について、意味が反転します。「不変の〜」、だとか、「変わらない〜」という意味を持ちます。
immutableなオブジェクトとは、変更不可能なオブジェクトをさす言葉です。
例として、int、float、などの数値型、文字列型や、tuple型などが挙げられます。
数値型ってことは......ちょっと待ってよ!
代入は変更に当たるんじゃないの?
a = 10 # aに値を代入している
a = 5 # 10が入っている a に、5を代入。
変数 a の値は10に変化した! → 変更しているのでは?
代入は変更には当たりません
代入がオブジェクトの変更に当たらないのは、10というオブジェクトの実態が変化していないからです。
それってどういうこと?
Pythonでは、identityと呼ばれる番号でオブジェクトにアクセスするようになっています。
代入で行われるのはidentityの書き換え。
つまり、オブジェクトの実態を変更していることにはなりません。
よって、代入はオブジェクトの変更には当たりません。
組み込み関数であるid()でidentityで確認してみよう
a = 10
print( "id(a) = ", id(a) )
print( "id(10) = ", id(10) )
a = 5
print( "id(a) = ", id(a) )
print( "id(10) = ", id(10) )
# 実行結果
# id(a) = 4512497008
# id(10) = 4512497008
# id(a) = 4512496848
# id(10) = 4512497008
実態のオブジェクトである10は、変数aに5を代入しても変わりません。
→ つまり、代入はオブジェクトの変更には当たりません。
→ 代入は参照先の変更でしかないのです。
小まとめ
Pythonでいうmutable、immutableとは、オブジェクトの実態が変化するか、しないかということで決まります!
複雑な例で考えてみよう
以下の二つは、それぞれ、mutableでしょうか、それともimmutableでしょうか。
complex_a = (1,2,3,[4,5])
complex_b = [1,2,3,(4,5)]
complex_aはimmutable
complex_a = (1,2,3,[4,5])
一番外側の要素がtupleなので、この変数はimmutableです(簡単な見分け方)。
complex_a[3].pop()などで操作はできます。が、リストの存在そのものを削除することはできません(tupleの機能でエラーとなります)。
complex_aのidentityが示す1や2、リスト[4,5]のidentityはtupleによって消えたり増えたりするしないことが保証されるので、complex_aはimmutableなのです。
complex_bはmutable
complex_b = [1,2,3,(4,5)]
一番外側がリストなので、mutableとなります。
complex_b.pop()などをしてやると、中に要素として入っている(4,5)自体が削除されます。すると、四つあったidentity番号が三つになります。
こんな風に、complex_bが保持していた直近のオブジェクトのidentityが消えたり増えたりするので、complex_bはmutableです。
最終まとめ
mutable、immutableは、一回のみの参照でたどり着けるオブジェクトのidentityが変化するか、変化しないかを表したもの
と言い換えできるのではではないでしょうか。