immutable
とは値を変えられないということ、というふうに言われるがpythonの場合は分かりづらい。
immutableとは変数の値が知らないところで書き換えられることがないことを示している。
文字列はimmutableと言われる。
C言語だと文字列はmutableになる。
1 2 3 |
char str[] = "abc"; char* p = str; str[1] = 'x'; // pも変わる |
pythonや多くの言語では上記のようなことはできず、文字列はimmutableになっている。
リストはmutable
mutableとは変数が知らないところで書き換わってしまうこと。
1 2 3 4 5 6 |
>>> a = [1,2,3] >>> b = a >>> a.append(4) >>> b [1, 2, 3, 4] >>> |
aとbは同じ実体を表すのでaに追加した4がbにも反映される。
しかし以下の場合は違う。
1 2 3 4 5 6 |
>>> a = [1,2,3] >>> b = a >>> a = [4,5,6] >>> b [1, 2, 3] >>> |
aに代入した[4,5,6]はもともとa,b両方が参照していたリストとは違うリストで新しく代入している。この場合はaとbは違うリストを参照している。
2つの変数が参照しているものが同じかどうかを調べるにはid()を使う。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
>>> a = [1,2,3] >>> b = a >>> id(a) 8053288 >>> id(b) 8053288 >>> >>> a = [4,5,6] >>> id(a) 6151432 >>> id(b) 8053288 >>> >>> |
文字列とリストでの関数の違い
しかし文字列でも同じid()を持つことはある。同じであってもそれが読み込みしかされていないなら問題はない。しかしそれを変更するわけにはいかないことから、このような違いは文字列とリストでの関数の違いとなって現れる。文字列の関数は常に新しい文字列を返し、自分自身を変更することはしない。リストの関数は常に自分自身を変更し、リストを返さない。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
>>> x = 'abc' >>> y = x >>> id(x) 6094944 >>> id(y) 6094944 >>> x.upper() 'ABC' >>> x 'abc' >>> y 'abc' >>> x = x.upper() >>> x 'ABC' >>> id(x) 8055104 >>> id(y) 6094944 >>> |
upper()は新しい文字列を返し、自分自身は変更しない。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
>>> a = [1,2,3] >>> b = a >>> id(a) 6151432 >>> id(b) 6151432 >>> a = a.append(4) >>> a >>> id(a) 1583959272 >>> id(b) 6151432 >>> a >>> b [1, 2, 3, 4] |
append()は何も返さず、自分自身を変更する。
注意点
このようなふるまいからリストを使うときは注意を要することがある。
1 2 3 4 5 6 |
>>> def getlist(): ... return [1,2,3] ... >>> l = getlist().append(4) >>> l >>> |
append()はリストを返さないのでlには何も入らない。以下のようにしないといけない。
1 2 3 4 5 |
>>> l = getlist() >>> l.append(4) >>> l [1, 2, 3, 4] >>> |