ミュータブル,イミュータブルとは
ミュータブル,イミュータブルは変数の型に対して使用する言葉で,Pythonの変数はミュータブルな型とイミュータブルな型に大別することができます.
・ミュータブルな型: リスト,辞書
・イミュータブルな型: int, float, 文字列, bool, タプル
イミュータブルな型の変数(以下イミュータブル)が普通の変数であり,いつもやっているように代入ができる変数のことです.
ミュータブルな型の変数(以下ミュータブル)もいつも普通に代入をしていると思っていても,実際の挙動は異なります.
イミュータブルは変数に新しく値を代入してら,更新されると共にメモリ内の変数があった位置(アドレス)も変更されます.しかし,ミュータブルな変数は新しく変数を代入し直してもアドレスが変更されません.
そのため,以下のようになります.
x = [1, 2, 3]
y = x
y.append(4)
print(x)
print(y)
出力
[1, 2, 3, 4]
[1, 2, 3, 4]
編集した変数はyのみですが,xの値も変更されてしまっています.これは,xもyもアドレスが同じため,同じ変数という扱いになるためです.
(ここではシャローコピー,ディープコピーの説明は省きます.気になる人は調べてみてください.)
そのため,以下のコードのように書きます.
x = [1, 2, 3]
y = x.copy()
y.append(4)
print(x)
print(y)
出力
[1, 2, 3]
[1, 2, 3, 4]
こうすることにより,xとyは別アドレスの別の変数になります.
また,ミュータブルな型の変数にミュータブルな型の要素がある多次元リストのような型の場合は上記のようにしても最終的な要素のアドレスが共通してしまうため,以下のようにします.
import copy
x = [[1, 2], [3, 4], [5, 6]]
y = copy.deepcopy(x)
関数の引数にミュータブルな型をいれる場合
上記のことから,関数の引数にミュータブルを指定しまうと,関数内でミュータブルを編集してしまっただけで引数元の内容も変わってしまいます.
そのため,通常引数にミュータブルを指定する場合は以下のようにしましょう.
def hoge(list_array):
list_array = list_array.copy()
list_array.append(4)
return list_array
このcopyする処理が大切です.